これを解決するためのベストプラクティスは何ですか?
if (... )
{
push (@{$hash{'key'}}, @array ) ;
}
else
{
$hash{'key'} ="";
}
1つの要素を格納するための悪い習慣は配列ですか、それともハッシュの二重引用符ですか?
これを解決するためのベストプラクティスは何ですか?
if (... )
{
push (@{$hash{'key'}}, @array ) ;
}
else
{
$hash{'key'} ="";
}
1つの要素を格納するための悪い習慣は配列ですか、それともハッシュの二重引用符ですか?
明示的な配列参照を使用する方がおそらく簡単です。
my $arr_ref = \@array;
$hash{'key'} = $arr_ref;
実際、上記を実行して使用push
すると、同じデータ構造が得られます。
my @array = qw/ one two three four five /;
my $arr_ref = \@array;
my %hash;
my %hash2;
$hash{'key'} = $arr_ref;
print Dumper \%hash;
push @{$hash2{'key'}}, @array;
print Dumper \%hash2;
これは与える:
$VAR1 = {
'key' => [
'one',
'two',
'three',
'four',
'five'
]
};
$VAR1 = {
'key' => [
'one',
'two',
'three',
'four',
'five'
]
};
明示的な配列参照を使用すると、使用する文字が少なくなり、push @{$hash{'key'}}, @array
構成体である IMO よりも読みやすくなります。
編集:ブロックの場合else{}
、空の文字列を割り当てるのはおそらく理想的ではありません。コンストラクトをスキップしてif-else
、後でハッシュ内の値にアクセスするときにif( defined( $hash{'key'} ) )
チェックを行う方がはるかに簡単です。これは標準的な Perl のイディオムに非常に近く、空の文字列をハッシュに格納するためにメモリを浪費することはありません。
代わりに、ref()
値に含まれるデータの種類を調べるために を使用する必要があります。これは、定義されているかどうかのチェックを行うよりも明確ではありません。
私はあなたの質問を理解しているかどうか確信が持てませんが、今求められているように文字通り答えます...
my @array = (1, 2, 3, 4);
my $arrayRef = \@array; # alternatively: my $arrayRef = [1, 2, 3, 4];
my %hash;
$hash{'key'} = $arrayRef; # or again: $hash{'key'} = [1, 2, 3, 4]; or $hash{'key'} = \@array;
問題の核心は、配列またはハッシュがスカラー値を取ることです...したがって、配列またはハッシュへの参照を取得し、それを値として使用する必要があります。
詳細については、 perlrefとperlreftutを参照してください。
編集:はい、空の文字列をいくつかのキーの値として追加し、他のキーの参照 (配列またはハッシュ、またはスカラー、タイプグロブ/ファイルハンドル、またはその他のスカラーへのいずれか) を追加できます。それらはすべてまだスカラーです。
ref
参照型と通常のスカラーの間のあいまいさを解消する方法を理解するために、関数を調べたいと思うでしょう。
あなたの目標が何であるかはわかりませんが、考慮すべき点がいくつかあります。
まず、配列を保存する場合、元の値への参照を保存しますか、それとも元の値のコピーを保存しますか? どちらの場合でも、間接参照構文を避け、可能な場合は参照を取得することを好みます。
$hash{key} = \@array; # just a reference
use Clone; # or a similar module
$hash{key} = clone( \@array );
次に、単一の値であっても、既に存在する値に追加しますか? 配列値を使用する場合は、要素が 1 つであっても、すべての値を配列にします。次に、何をすべきかを決定する必要はなく、特別なケースを削除します。
$hash{key} = [] unless defined $hash{key};
push @{ $hash{key} }, @values;
これは、多くの場合、できるだけ多くの特殊なケースと余分なロジックを削除する手法です。モジュールでこの種のことを行うとき、私は通常、add_value
この魔法をカプセル化するメソッドを使用します。メソッドを表示したり、複数回入力したりする必要はありません。
ハッシュキーに非参照値がすでにある場合、それも簡単に修正できます。
if( defined $hash{key} and ! ref $hash{key} ) {
$hash{key} = [ $hash{key} ];
}
配列に入れたい非配列参照値がすでにある場合は、同様のことを行います。匿名ハッシュを配列要素の 1 つにしたい場合があります。
if( defined $hash{key} and ref $hash{key} eq ref {} ) {
$hash{key} = [ $hash{key} ];
}
改訂された表記法への対処:
if (... )
{
push (@{$hash{'key'}}, @array);
}
else
{
$hash{'key'} = "";
}
初心者 (およびエキスパート!) を自分の過ちから守る標準的なアドバイスに従っていないことがすぐにわかります。シンボリック参照を使用していますが、これはお勧めできません。
use strict;
use warnings;
my %hash = ( key => "value" );
my @array = ( 1, "abc", 2 );
my @value = ( 22, 23, 24 );
push(@{$hash{'key'}}, @array);
foreach my $key (sort keys %hash) { print "$key = $hash{$key}\n"; }
foreach my $value (@array) { print "array $value\n"; }
foreach my $value (@value) { print "value $value\n"; }
これは実行されません:
Can't use string ("value") as an ARRAY ref while "strict refs" in use at xx.pl line 8.
あなたが達成しようとしていたことを理解できるかどうかわかりません。「use strict;」を削除しても 警告、示されているコードは操作からの変更を検出しませんpush
。
use warnings;
my %hash = ( key => "value" );
my @array = ( 1, "abc", 2 );
my @value = ( 22, 23, 24 );
push @{$hash{'key'}}, @array;
foreach my $key (sort keys %hash) { print "$key = $hash{$key}\n"; }
foreach my $value (@array) { print "array $value\n"; }
foreach my $value (@value) { print "value $value\n"; }
foreach my $value (@{$hash{'key'}}) { print "h_key $value\n"; }
push @value, @array;
foreach my $key (sort keys %hash) { print "$key = $hash{$key}\n"; }
foreach my $value (@array) { print "array $value\n"; }
foreach my $value (@value) { print "value $value\n"; }
出力:
key = value
array 1
array abc
array 2
value 22
value 23
value 24
h_key 1
h_key abc
h_key 2
key = value
array 1
array abc
array 2
value 22
value 23
value 24
value 1
value abc
value 2
何が起こっているのかわかりません。
問題が、以前に保存した空の文字列値を、値をプッシュできる配列に置き換える方法である場合、これが最善の方法かもしれません。
if ( ... ) {
my $r = \$hash{ $key }; # $hash{ $key } autoviv-ed
$$r = [] unless ref $$r;
push @$$r, @values;
}
else {
$hash{ $key } = "";
}
%hash
。