• ベストアンサー

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

ハッシュ内の各値部分に配列を展開したいのですが、下記のようにしてみてるのですが、配列が全部展開されず、はまっております。宜しければご教授願えませんでしょうか。 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'], }; お手数ですが宜しくお願い致します。

  • taku0
  • お礼率80% (160/199)
  • Perl
  • 回答数4
  • ありがとう数3

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

  • ベストアンサー
  • 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

  • awkで二つのファイルを比較し出力する方法

    UNIXで二つのファイルを使って別ファイルを出力する 処理をしたいのですが、awkで二つのファイルを扱う方法 が分かりませんでした。 やりたい処理は以下のような事です。 ファイルAの1行目"AAA B"と同じ行がファイルBにあったら、ファイルAの"AAA B"の次の行に、 ファイルBの次の行"YYY bbb"を挟み込みます。 もし、ファイルBに同じ行がなかったら、 ファイルAの次の行に"NG"を挟み込みます。 [ファイルA] AAA B ZZZ B AAA C ZZZ C AAA D ZZZ D [ファイルB] AAA B YYY bbb AAA C YYY bbb [出力ファイル] AAA B YYY bbb ZZZ B AAA C YYY ccc ZZZ C AAA D NG どなたか良いスクリプトありましたら 教えていただけないでしょうか。 よろしくお願いします。

  • 無名配列からハッシュを作りたいのですが・・・

    $VAR1 = [ 'No', 'a', 'i', 'u', 'e', 'o', ]; #VAR1と同じ数の<>区切りの下記のようなデータを読み込み配列に代入 --List----------------------- 1<>あ<>い<>う<>え<>お<> ------------------------- foreach(0..$#List){ @Array=split(/<>/,$List[$_]); } 最終的なイメージは print "$a{No}"; >1 print "$a{a}"; >a となるよう、上記VAR1の無名配列の値をキーに、読み込んだ<>区切りのデータを関連付けて表示させるようにしたいのです。 foreach my$var(@$VAR1){ ...ここをどうすれば配列の値をハッシュのキーとして作成出来るのか頭を悩ませてます。 } 先輩方のお知恵をお借りできませんでしょうか。 宜しくお願いします。

    • ベストアンサー
    • Perl
  • 配列やハッシュで中身が同じか簡単に調べることは可能でしょうか?

    スカラ型なら my $a = "a"; my $b = "b"; if( $a eq $b)の用に比較が簡単に出来ますが、 配列やハッシュはどのように中身が同じかどうか調べることは可能でしょうか? 配列でも複雑な(例えば配列のデータがハッシュ値)のような以下の ものを中身が同じが比較する方法です。 固定でなく、どんなデータが入ってきても数やキーが異なっても比較する方法が知りたいです。 my @ary1 = (); $ary[0]{'test_a'} = "a"; $ary[0]{'test_b'} = "b"; $ary[1]{'test_a'} = "aa"; $ary[1]{'test_b'} = "bb"; my @ary2 = (); $ary[0]{'test_a'} = "aa"; $ary[0]{'test_b'} = "bb"; $ary[1]{'test_a'} = "aaa"; $ary[1]{'test_b'} = "bbb";

    • ベストアンサー
    • Perl
  • ある条件で一致した場合、配列に代入したい

    foreach(0..$#DataLines){ my@aaa= split(/<>/,$DataLines[$_]); if($FORM{No} eq @aaa[1]){ unshift(@bbb,"$DataLines[$_]"); } } print F "@bbb"; した時に配列@bbbにif($FORM{No} eq @aaa[1]){ で一致した場合、その時の配列を全部@bbbに代入したいのですが、最後のしか入らないようなので、これを全部入れるにはどうすれば良いかご教授願えませんでしょうか。 宜しくお願い致します。

    • ベストアンサー
    • Perl
  • 無名配列や無名ハッシュの値を変更し保存する際、

    Data::Dumper(Data::Dumperにこだわるわけではないのですが)を使って無名配列or無名ハッシュの値(40万行程度あると仮定。 例) $VAR1 = { 'aaa' => {'get' => '1','all' => '0'}, 'bbb' => {'get' => '1','all' => '1'}, } といった形)を変更後、保存する場合、その配列orハッシュ全体を読み込んで保存する形になるのでしょうか、それとも、配列orハッシュ全体を読み込まず各値に対するアドレスから実体(リファレンス/シンボリックリファレンスの概念が明確にわかってないのですが)へアクセスして値を変更=そのまま保存するようになのでしょうか。 諸先輩or先生方、お手数ですがこの辺りの仕組みについてご教授願えますと幸いです。宜しくお願い致します。

    • ベストアンサー
    • Perl
  • 要素名を表示させたい

    <data>   <aaa xxx="0">     <yyy zzz="1"/>     <yyy zzz="2"/>   </aaa>   <bbb xxx="0">     <yyy zzz="1"/>     <yyy zzz="2"/>   </bbb>   <ccc xxx="0">     <yyy zzz="1"/>     <yyy zzz="2"/>   </ccc> </data> 上のようなXMLから、XSLのvalue-ofなどを使って、 要素名aaa、bbb、cccを表示させるにはどう記述すればいいのでしょうか?

    • ベストアンサー
    • XML
  • 静的ハッシュの配列のキーに対応する値の数の多さ順で表示させたい

    ハッシュのキーに対応する値の数の多さ順で表示させたいと考え、下記の所まで試行錯誤しておりますが、どうにも思ったようにソートできずにおります。 #!/usr/bin/perl use strict; my(%a, $i, $j ,$allarray ,@keys ,@keys2 ,%hash ,%files ,$a_mumei_ref ,$key ,$value ,@value ,$x ,$files); # ハッシュの配列を静的に作る %a = ( '0' => [ qw(0) ], '1' => [ qw(1 1) ], '3' => [ qw(3 3 3) ], '7' => [ qw(7 7 7) ], '2' => [ qw(2) ], '4' => [ qw() ], '5' => [ qw() ], '6' => [ qw() ], '8' => [ qw(8 8) ], '9' => [ qw(9) ], ); @keys = sort { $hash{$b} <=> $hash{$a} || length($b) <=> length($a) || $a cmp $b } keys %a; #ハッシュのキーを数字順で表示 foreach (@keys){ print $_ ."\n"; } # 静的に作ったハッシュの配列を取り出してみる foreach $i (sort keys %a) { for ($j = 0; $j <= scalar(@{$a{$i}})-1; $j++) { print '$a{'. $i. '}['. $j. ']='. $a{$i}[$j]. ' '; } $allarray=scalar(@{$a{$i}})-1; print "No$i:kosuu:$allarray"; print "\n"; #配列の値の個数を調べその配列を作成 my($a_mumei) = $allarray; $a_mumei_ref = \$a_mumei; $files{"$i"}=($i,$a_mumei_ref); } #each関数で%filesの中身を表示 while ( ( $key , $value ) = each %files ){ print "key:$key value:$$value\n" ; } #試行錯誤 foreach $x (sort { $files{$b} <=> $files{$a} } keys %files){ print "$x => $files->{$x}\n"; } @keys2 = sort {$hash{$a} <=> $hash{$b}} keys %files; #@keys2 = sort { $hash{$b} <=> $hash{$a} || length($b) <=> length($a) || $a cmp $b } keys %files; #@keys2 = sort { $hash{$a} cmp $hash{$b} } keys %files; print "@keys2\n"; print "\n"; __END__; 私のイメージしておりますのは、ソートした結果がハッシュのキーに対応する値の数の多さ順で下記のように表示させたいのですが、 どのようにすれば可能でございますか、ご教授願えませんでしょうか key:3 value:2・・・この場合valueは配列の個数 key:7 value:2 key:8 value:1 key:1 value:1 key:9 value:0 key:2 value:0 key:0 value:0 key:6 value:-1 key:4 value:-1 key:5 value:-1

    • ベストアンサー
    • Perl
  • 行数ごとに検索をかけて並び替えをしたいのですが・・

    数千のファイル名が書かれたテキストファイルがあります。(Aとします。) /yyy/ccc.txt /aaa/aaa.txt /bbb/bbb.txt /sss/aaa.txt /ccc/bbb.txt /zzz/ccc.txt ・ ・ ・ ユニークファイル名だけ書かれたファイルがあります。(Bとします。) aaa.txt bbb.txt ccc.txt ・ ・ ・ Bの行数1行ずつAで検索をかけ、ファイル名を新しいファイル(Cとします)に書き出したいのです。 /aaa/aaa.txt /sss/aaa.txt /bbb/bbb.txt /ccc/bbb.txt /yyy/ccc.txt /zzz/ccc.txt ・ ・ ・ シェルを使ってやりたいのですが、どのようにすればいいのか見当もつきません。 どなたかお分かりのかたいましたら教えてください。よろしくおねがいします。

  • ファイル入出力と配列について。

    aaa 1 a bbb 2 b ccc 3 c このようなファイルを読み込んで、 配列に入れてたいのですが、 やり方がわかりません。 どなたか教えてください。 お願いします。

  • シェルスクリプトにてファイルの結合

    お世話になります。 ある3つのファイルfile1 file2 file3 の内容が file1が 111 222 333 file2が aaa ddd bbb eee ccc fff file3が xxx yyy zzz という内容を file4に 111 aaa ddd xxx 222 bbb eee yyy 333 ccc fff zzz という具合に横に結合させて出力させたいのですが どうしていいか分かりません。 sedとかawkを使えばいけそうなんですが 分かる方いらっしゃいませんか??? 宜しくお願いいたします。

専門家に質問してみよう