7

もともと、長さ= 2 ^ 16のリストを扱っています。ただし、これを抽象化するために、この例では length = 5 に設定します。

#subroutine to make undefined entries -> 0
sub zeros {
    foreach(@_) {
        if(!defined($_))    {
            $_ = 0;
        }
    }
}       
 #print out and indicies and elements of list 
    sub checking {
        print "List = \n";
        my $counter = 0;
        foreach (@_) { 
            print "index = $counter\n";
            print "$_\n";
            $counter += 1;
        }
            print "\n";
    }

方法 1 : 要素を編集するために別のインデックスにアクセスすると、配列を出力すると次のようになります。私は空白を見たくありません。それらを 0 にしたい。未定義のエントリをゼロにするサブルーチン「zeros」を既にセットアップしています。しかし、コードで何が問題になったのかわかりません。リストの各要素に対して「$_ += 0」も試しました。空のエントリに対してまだゼロを取得できませんでした。

#method 1
@abc = ();
$abc[1] = 3;
$abc[5] = 5;
&zeros(@abc);
&checking(@abc);
List = 
index = 0

index = 1
3
index = 2

index = 3

index = 4

index = 5
5

そして方法 2 : このようにリストを初期化すると、ゼロを取得できます。しかし、私が言ったように、私は非常に長いリストを扱っているので、このようにリストを初期化することは絶対にできません。

#method 2
@abc = (3,0,0,0,5);
&checking(@abc);

List = 
index = 0
3
index = 1
0
index = 2
0
index = 3
0
index = 4
5
4

4 に答える 4

4

あなたのアプローチは正しいですが、zeros()機能に問題があります。@abcそのリストのコピーを作成するパラメータとしてそれを呼び出しています。次に、コピーを変更します。サブの最後に、そのコピーは破棄されます。checking()関数では、まだ元のリストを使用しています。

次のように修正できます。

sub zeros {
  my @list = @_;
  @list = map { $_ // 0 } @list;
  return @list;
} 

@abc = zeros(@abc);
checking(@abc);

トリックは、変更されたリストを返し、それを元の変数に再割り当てすることです。

もしあなたが使っていたらstrictwarningsそれについてあなたに言ったでしょう:

Use of uninitialized value $_ in concatenation (.) or string at F:\scratch.pl line 28. List =  index = 0

index = 1 3 index = 2

index = 3

index = 4

index = 5 5

Use of uninitialized value $_ in concatenation (.) or string at F:\scratch.pl line 28. 
Use of uninitialized value $_ in concatenation (.) or string at F:\scratch.pl line 28. 
Use of uninitialized value $_ in concatenation (.) or string at F:\scratch.pl line 28.

ただし、非常に大きな配列を扱っているため、コピーにはコストがかかるため、代わりに配列参照を使用することをお勧めします。

sub zeros {
  $_ //= 0 for @{ $_[0] };
} 

zeros(\@abc);
checking(@abc);
于 2013-08-06T20:57:04.903 に答える
1
use 5.010;
$_ //= 0 for @abc;

5.10 より前の perl では、

$_ = defined($_) ? $_ : 0 for @abc;

関数に変換したい場合は、置換がインプレースであるため、値を返さないでください。

use 5.014;
use strict;
use warnings;
use YAML;

my @abc;
$abc[1] = 3;
$abc[5] = 5;

print Dump \@abc;

map_undefined_entries_to_zeros(\@abc);

print Dump \@abc;

sub map_undefined_entries_to_zeros {
    my $array_ref = shift;
    $_ = defined($_) ? $_ : 0 for @$array_ref;
    return;
}
于 2013-08-06T21:32:37.113 に答える
1

undef 要素を遅延またはオンデマンドでゼロに置換したい場合は、次tieのように配列を変更できます。

package Ad::Hoc::UndefToZero;

use Tie::Array;
our @ISA = qw(Tie::StdArray);

sub FETCH {
  my ($tied, $i) = @_;
  my $elt = $tied->SUPER::FETCH($i);
  unless (defined $elt) {
    $elt = 0;
    $tied->STORE($i, $elt);   # $tiedarray[$i] is now zero
  }
  $elt;
}

package main;

tie my @abc, 'Ad::Hoc::UndefToZero';
$abc[1] = 3;
$abc[5] = 5;

print "$abc[0]\n";  # $abc[0] now set to zero
于 2013-08-07T04:41:44.780 に答える