• ベストアンサー

ハッシュ内の各値部分に配列を展開したい

ハッシュ内の各値部分に配列を展開したいのですが、下記のようにしてみてるのですが、配列が全部展開されず、はまっております。宜しければご教授願えませんでしょうか。 use Data::Dumper; $Data::Dumper::Indent = 1; $dumpfile='dump.txt'; my @all = (aaa ,bbb); my @cate = qw(yyy zzz); my %hash; foreach my $a ( @all ) { foreach $b ( @cate ) { $hash{$a}[$b] = "$b"; } } open(F,"> $dumpfile") ; print F Dumper(\%hash); close(F); ■実行結果 $VAR1 = { 'bbb' => [ 'zzz' ], 'aaa' => [ 'zzz' ] }; ■イメージしている形 $VAR1 = { 'bbb' => ['yyy','zzz'], 'aaa' => ['yyy','zzz'], }; お手数ですが宜しくお願い致します。

質問者が選んだベストアンサー

  • ベストアンサー
  • moon_piyo
  • ベストアンサー率60% (88/146)
回答No.1

こんにちは 結果から考えると... $hash{$a}[$b] = "$b"; ↓ push @{$hash{$a}}, $b; と修正すればいいような

taku0
質問者

お礼

まさしく該当箇所の変更で、イメージ通りになりました。 pushとかも使うのかな・・という印象はあったのですが、どうすれば良いかわからず、途方に暮れておりましたが、これで胸の内がすっきりしました。 ご教授頂きまして有難うございます。

すると、全ての回答が全文表示されます。

その他の回答 (3)

回答No.4

実際行われる処理に適当かどうかわかりませんが、 ご提示されたイメージしている形を実現する目的なら、 map 演算子を用いると、perl っぽくシンプルに書けます。 以下、ソース -------------------------------------------------------------------------------- #!/usr/local/bin/perl use strict; use warnings; use Fatal qw(open close); use Data::Dumper; $Data::Dumper::Indent = 1; my $dumpfile = 'dump.txt'; my @all = qw(aaa bbb); my @cate = qw(yyy zzz); my %hash = map { $_ => [ @cate ] } @all; # ここです open my $fh, '>', $dumpfile; print {$fh} Dumper(\%hash); close $fh; --------------------------------------------------------------------------------

taku0
質問者

お礼

map 演算子を使うと1行で解決できてしまうんですね。大変勉強になります。今までgrepは使う機会あったんですが、mapについては使う機会がなくgrepとの違いもよく理解できていないので、今後は注意してmapを意識してみるようにしたいです。 有難うございました。

すると、全ての回答が全文表示されます。
  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.3

いけね。 一箇所修正漏れ。 #$hash1{$row}[$col] = $col; $hash1{$row}{$col} = $col; #2で貼り付けた実行結果は上のコメントアウトされている方です。

すると、全ての回答が全文表示されます。
  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.2

>$hash{$a}[$b] = "$b"; $b には文字列が入ってくるのだから、[ $b ] のように数値で インデクシングする配列に使っちゃいけませんね。 右辺の $b をクォートするのも意味不明だし。 Argument "yyy" isn't numeric in array element at mmm.pl line 17. Argument "zzz" isn't numeric in array element at mmm.pl line 17. foreach my $a ( @all ) { このループで列挙される要素に配列のリファレンスを入れればいいのだから push @{$hash3{$row}}, [ @cate ]; でいいでしょう。 内側の foreachは不要です。 全部を貼り付けるとこんな感じ use strict; use warnings; use Data::Dumper; $Data::Dumper::Indent = 1; my $dumpfile = 'dump.txt'; my @all = qw(aaa bbb); my @cate = qw(yyy zzz); my %hash1; my %hash2; my %hash3; foreach my $row ( @all ) { foreach my $col ( @cate ) { #$hash1{$row}[$col] = $col; $hash1{$row}{$col} = $col; push @{$hash2{$col}}, $col; } push @{$hash3{$row}}, [ @cate ]; } open my $fh,'>', $dumpfile or die $!; print $fh Dumper(\%hash1); print $fh "#######\n"; print $fh Dumper(\%hash2); print $fh "#######\n"; print $fh Dumper(\%hash3); close $fh; dump.txt の内容はこう。 $VAR1 = { 'bbb' => [ 'zzz' ], 'aaa' => [ 'zzz' ] }; ####### $VAR1 = { 'yyy' => [ 'yyy', 'yyy' ], 'zzz' => [ 'zzz', 'zzz' ] }; ####### $VAR1 = { 'bbb' => [ [ 'yyy', 'zzz' ] ], 'aaa' => [ [ 'yyy', 'zzz' ] ] };

taku0
質問者

お礼

確かに[$b]部分は数字なので[$b]として展開するのは間違いですね。 指摘されてみてはたときずかされてしまいます。 またテストの確認方法が、一箇所修正してテストではなく、ハッシュをいくつか作って同時にテストすれば、どんな事をどこでテストしているのかという 流れが把握できて分かりやすかったので、今後の参考にさせて頂きたいと思います。 また実行結果ですけれども、 $VAR1 = { 'bbb' => {'yyy' => 'yyy','zzz' => 'zzz'}, 'aaa' => {'yyy' => 'yyy','zzz' => 'zzz'} }; ####### $VAR1 = { 'yyy' => ['yyy','yyy'], 'zzz' => ['zzz','zzz'] }; ####### $VAR1 = { 'bbb' => [['yyy','zzz']], 'aaa' => [['yyy','zzz']] }; ご教授頂いたとおりとなりまして、意図している結果にはなっておりませんでした。ですが、大変勉強になりました。どうも有難うございました。

すると、全ての回答が全文表示されます。

関連するQ&A