• ベストアンサー

動的なハッシュの配列を作成したい

#お世話になります。最終的には、下記のように配列の順番にハッシュを作成したいのですが、ご教授願えませんでしょうか #!/usr/bin/perl #想定される配列 @array=(0,2,4,6,8,1,3,5,7,9); #下記が最終的に動的に作成したいハッシュの形です。 %List = ( '0' => [ (@array0_n) ], '2' => [ (@array2_n) ], '4' => [ (@array4_n) ], '6' => [ (@array6_n) ], '8' => [ (@array8_n) ], '1' => [ (@array1_n) ], '3' => [ (@array3_n) ], '5' => [ (@array5_n) ], '7' => [ (@array7_n) ], '9' => [ (@array9_n) ], ); $a='array'; $n='_n'; foreach (@array){ #試行錯誤中... print "\@{${a}[$_]{$n}}=@{${a}[$_]{$n}}"; } __END__; お忙しいかとは存じますが、よろしくお願いいたします。

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

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

  • ベストアンサー
  • nerumako
  • ベストアンサー率84% (11/13)
回答No.3

ざっと見たところ、リファレンスを使われたいのではないでしょうか。 それと、「最終的に動的に作成したいハッシュ」の%Listについては '0' => [ (@array0_n) ], と書かれている通り各keyに対してのvalueは配列が入る事になりますので @array0_n~@array9_nの要素はハッシュ作成の処理を行う前に用意しなくてはなりませんね。 と、勝手に仮定しまして下記処理を書いてみました。 #--------------------------------------------------- @array=(0,2,4,6,8,1,3,5,7,9); ### 勝手に要素を用意しました @array0_n=('a','b','c'); @array2_n=('d','e','f'); @array4_n=('g','h','i'); @array6_n=('j','k','l'); @array8_n=('m','n','o'); @array1_n=('p','q','r'); @array3_n=('s','t','u'); @array5_n=('v','w','x'); @array7_n=('y','z','aa'); @array9_n=('ab','ac','ad'); foreach(@array){ my $x="array$_\_n"; $List{$_}=[(@$x)]; print "@$x<br>"; } #--------------------------------------------------- @arrayの要素番号0~ をハッシュのkeyとして、 valueを(@array要素番号_n)と言う配列名として、 実質、配列要素の順番にハッシュを作成した事になります。 もちろんハッシュを作成する順番の事であって、他の方が言われる通りハッシュのkey,valueの並び順を保障するモノではありません。 #下記が最終的に動的に作成したいハッシュの形です。 結果的に↑になっているのではないでしょうか。 ハッシュに対してシンボリックリファレンスを使って動的に配列を入れてます。(まずいですか?) ご存知かとは思いますが%Listの各要素を確認するには print $List{0}[1]; とかになります。 ちょっと質問の情報量が少なめなので ほとんど推理に近い憶測で書いてみました。

taku0
質問者

お礼

>それと、「最終的に動的に作成したいハッシュ」の%Listについては >'0' => [ (@array0_n) ], >と書かれている通り各keyに対してのvalueは配列が入る事になりますので >@array0_n~@array9_nの要素はハッシュ作成の処理を行う前に用意しなくてはなりませんね。 仰る通りです。これは前もって用意されている前提でございました。 >@arrayの要素番号0~ をハッシュのkeyとして、 >valueを(@array要素番号_n)と言う配列名として、 >実質、配列要素の順番にハッシュを作成した事になります。 > >ハッシュに対してシンボリックリファレンスを使って動的に配列を入れてます。(まずいですか?) ありがとうございます。まさしく! >foreach(@array){ >my $x="array$_\_n";#array$_\_nを代入するんですね。 >$List{$_}=[(@$x)];#そして、リファレンスにする為に[]でくくって配列を展開させる為に(でくくるっていう事なんでしょうか・・。この辺りがどうにも分からない部分でいつも試行錯誤してしまう部分です。) > >print "@$x<br>"; >%Listの各要素を確認するには >print $List{0}[1]; >とかになります。 ですね。$List{0}・・・?と一瞬思うんですが、キーが数字ですので、そうなるんですよね。 情報=前提少なめですいませんでした。 ありがとうございました。

その他の回答 (4)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.5

[...] は配列リファレンスを作りますぜ>#4. ついでにいうと中に対して配列コンテキストを要求します. つまり [@{$x}] は $x を (シンボリック) リファレンスとする配列の中身をそのまま持つような配列リファレンスを作ります. [...] が配列コンテキストを要求するのがポイントで, そうじゃない (つまりスカラコンテキストだ) と @{$x} が「要素数」に変換されてしまいます. で, 今の場合の () は完全にオプショナルです. [...] が配列コンテキストを要求しているので中の (@{$x}) は配列コンテキストで評価されますが, その場合 () は単に冗長なだけです.

taku0
質問者

お礼

実に分かり易い詳細な補足説明ありがとうございます。

  • nerumako
  • ベストアンサー率84% (11/13)
回答No.4

>my $x="array$_\_n";#array$_\_nを代入するんですね。 その通りです。 >$List{$_}=[(@$x)];#そして、リファレンスにする為に[]でくくって配列を展開させる為に(でくくるっていう事なんでしょうか・・。この辺りがどうにも分からない部分でいつも試行錯誤してしまう部分です。) > 2つ違います。  × リファレンスにする為に[]でくくって  × 配列を展開させる為に(でくくる $List{$_} はハッシュの入れ子です。$List{key}に対して配列 @$xを代入しています。 以下は同じ意味を持ちます。 %List = ('key' => 'value'); $List{key}='value'; ↑後者のようにスカラーに代入するようにハッシュを作れます。 ハッシュなんて言っても本当の正体は$スカラーなんです。配列もしかり。 それと @$xは$xに代入した文字列「array数字_n」を無理やり配列名に解決してしまっているようなものでそれ自体がシンボリックリファレンスらしいです。私は普段まったく使いません。 >配列を展開させる為に(でくくる () でくくるのは質問のソースに記述してあったのでノリでそのまま付けました。 配列を展開させるのではなく、配列を格納するためです。 配列格納の印として[]を用います。今回のように変数を入れる場合は()が無くて良いです。あっても動きますので結構適当です。 似たような記号だらけで本当いやになっちゃいますよね。 オマケにもうひとつ  × この辺りがどうにも分からない部分で 作り手が解らない部分があったままのスクリプトを動かすのでは コンピューターが困りますよね。 そのまま共用サーバーなどにスクリプトをアップするのであれば 路上で操作方法が解らないのに車を運転しているのと同じように危ないですから注意したいですよね。 解らない部分はとことん調べましょう。どんどん聞いても良いです。 今回はハッシュが多次元化してしまっていますが、 配列、ハッシュの基本操作を覚えてしまえば全然問題ないと思います。

taku0
質問者

お礼

お返事遅くなりました。 改めて色々とご教授頂いている事、感謝いたします。 ありがとうございます。

  • pick52
  • ベストアンサー率35% (166/466)
回答No.2

ハッシュというのはPerlで連想配列を実装するために使用されている アルゴリズムの名前です。 ハッシュは順番を固定せずにコンピュータが扱いやすいように自動で 内部的にソートしてしまうので順番を保持できません。 ハッシュは高速に動作するので連想配列に実装によく利用されていますが ハッシュそのものは連想配列だけのものでもないし連想配列の実装の アルゴリズムもハッシュのみではありません。 http://ja.wikipedia.org/wiki/%E3%83%8F%E3%83%83%E3%82%B7%E3%83%A5%E9%96%A2%E6%95%B0 で、Perlの連想配列で順番を固定したい場合は Tie::IxHash という モジュールを使用します。 http://katsubemakito.net/cgiperl/variable/hash/post-46.html

taku0
質問者

お礼

Tie::IxHash というのがあるんですか、ご教授頂きありがとうございます。 ハッシュのキーに順番付けができるんですね。何だか面白そうです。 少し試行錯誤してみたいと存じます。 ありがとうございました。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

ハッシュではキーと値の対応関係のみが重要であって, 「キー (や値) の順番」は意味を持ちません. つまり, 例えば my %a = (a => 'x', b => 'y'); my %b = (b => 'y', a => 'x'); とやると %a と %b は同じ内容のハッシュになります. なので, 「配列の順番にハッシュを作る」と言われても「それはどういうことでしょうか?」となります. あとついでに @array0_n とかって, 何を意味するんでしょうか?

taku0
質問者

お礼

ご教授頂きありがとうございます。 >「キー (や値) の順番」は意味を持ちません に意味を持たせられないか・・・と言うのが出発点でしたので、今回配列の順番にハッシュを作りたかったのでございます。 意味を持たせてどうしたいのか・・・部分につきましては、上記のお方に参考URLを掲示して頂いておりますのでそれを参考に少し試行錯誤してみようかと存じます。 @array0_nの意味は、配列を管理する為にn?とnの後ろに数字をつけている為でございました。

関連するQ&A

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

    $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
  • 静的ハッシュの配列のキーに対応する値の数の多さ順で表示させたい

    ハッシュのキーに対応する値の数の多さ順で表示させたいと考え、下記の所まで試行錯誤しておりますが、どうにも思ったようにソートできずにおります。 #!/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
  • 二次元配列のハッシュ版の記述方法?

    二次元配列のハッシュ版を実現させたいのですが、 以下の記述で正しいでしょうか? 構文に疎いので教えてください。 #!/usr/bin/perl %HASH_TEST = ( 'あ'=>{'A'=>'1', 'B'=>'2', 'C'=>'3'}, 'い'=>{'A'=>'4', 'B'=>'5', 'C'=>'6'}, ); print $HASH_TEST{'い'}{'B'}; #=> 5が表示されます。 exit; __END__

    • ベストアンサー
    • Perl
  • ソート時同じ値がある場合、表示順をコントロールする事は可能ですか?

    ハッシュの配列を配列の数の多い順に表示する場合で配列の数が同じの場合の最初に表示される配列の数字につきまして この配列の数が同じである場合の表示順序を意図した順番にする事は可能でございますか? この意図した順番と申しますのは、小さい数字を先に表示するのではなく下記の@array2の配列値の並んでいる順や別途配列に0~9の数字を適当に入れておきにそれを参考に評価するという形を希望しており模索中なのですが、まずこの事につきまして可能か不可能かをご教授願いたいのと、もし可能でしたらどうか解決に至る先輩方のお知恵をお借り出来ませんでしょうか よろしくお願い致します。 #!/usr/bin/perl use Tie::IxHash; @array0_n=('a','b','c','d'); @array1_n=('e','f','g'); @array2_n=('h','i'); @array3_n=('j'); @array4_n=(); @array5_n=(); @array6_n=('k'); @array7_n=('l','n'); @array8_n=('m','o','p'); @array9_n=('q','r','s','t'); %array1 = ( '0' => [ (@array0_n) ], '1' => [ (@array1_n) ], '2' => [ (@array2_n) ], '3' => [ (@array3_n) ], '4' => [ (@array4_n) ], '5' => [ (@array5_n) ], '6' => [ (@array6_n) ], '7' => [ (@array7_n) ], '8' => [ (@array8_n) ], '9' => [ (@array9_n) ], ); #配列の数の多い順に並び替え my @array2 =reverse sort { scalar @{$array1{$b}} <=> scalar @{$array1{$a}} or $a <=> $b } keys %array1; @array9_n2=('a2','b2','c2','d2'); @array1_n2=('e2','f2','g2'); @array2_n2=('h2','i2'); @array3_n2=('j2'); @array4_n2=(); @array5_n2=(); @array6_n2=('k2'); @array7_n2=('l2','n2'); @array8_n2=('m2','o2','p2'); @array0_n2=('q2','r2','s2','t2'); tie %TmpList, 'Tie::IxHash'; #@array2を元に更に動的にハッシュ内に配列を作成 foreach(@array2){ my $x="array$_\_n2"; $TmpList{$_}=[(@$x)]; print "$_,$#{$x},@$x<br>\n"; } print "1-end\n"; while ( ( $key , $value ) = each %TmpList ){ print "key:$key value:@$value\n" ; } print "2-end\n"; my @array3 = sort { scalar @{$TmpList{$b}} <=> scalar @{$TmpList{$a}} or $a <=> $b } keys %TmpList; #Tie::IxHashモジュールで表示する際の順番を固定出来るかテスト foreach(@array3){ my $x="array$_\_n2"; $TmpList2{$_}=[(@$x)]; print "$_,$#{$x},@$x<br>\n"; } print "3-end\n"; __END__;

    • ベストアンサー
    • Perl
  • ハッシュのリファレンスを用いた処理

    ActivePerl 5.8 , WinXP SP2の環境です。 Perl スクリプトを用い、ファイルから複数のブロックからなる情報をよみとり、個別のハッシュを作り、それをリファレンスの配列としてまとめて後から参照するという操作をしたいのですが、詰まってしまいました。。 例として読み取るファイルは ---input.txt--------- >1 Jan 1 Feb 4 >2 Mar 9 Apr 3 >3 Oct 8 Nov 4 ------------------ ここから1,2,3の個別のハッシュ {Jan => 1 Feb => 4} {Mar=> 9 Apr =>3} {Oct =>8 Nov =>4} を作成し、それぞれのハッシュのリファレンスの配列をつくり、その後からすべてのハッシュの中身を個別に出力させたいと思いました。 次のようなスクリプトを作成したのですが思ったように作動しません。 use strict; open (IN, "input.txt") or die ("cant open file \n"); my $reff; my @array_of_reff; my %hash; my $count = 0; while(<IN>){ my $line = $_; ######ここでは各ブロックの頭の ">"を認識し、2個目以降であれば直前までで作ったハッシュのリファレンス($reff)を配列@array_of_reffに入れる。 if($line =~ /^>/){ if($count >0){ $reff = \%hash ; push (@array_of_reff, $reff); %hash = (); } $count++; } ########ここではアルファベットが入った行を認識して、ハッシュに追加しています if($line =~ /^[A-Za-z]/){           $line =~ /([A-Za-z]+)\s+/; my $month = $1; $line =~ /\s+(\d+)/; my $day= $1; $hash{$month} = $day;     } ###ここはファイルの最後になったら直前まで作っていたハッシュののリファレンス($reff)を配列@array_of_reffに入れる。 if( eof ){ $reff = \%hash ; push (@array_of_reff, $reff); } } #####ハッシュのリファレンスの配列(@array_of_reff)からもとのハッシュを参照し、ハッシュごとに出力 foreach my $reff_of_hash (@array_of_reff){    print "output";    while( (my $key,my $value) = each %$reff_of_hash ){     print "\n" , $key, " : ", $value, ;    } } このスクリプトを実行すると Nov 4 Oct 8 という3つめのハッシュのなかみが3回出力されてしまいます。自分では3つの別のハッシュをつくっているつもりでも、どうやら1種類しか作れていない、もしくはハッシュが上書きされているようなのですが、原因がわかりません。 この例だけ見るとハッシュのリファレンスを使う必要はないのですが、実際にはもうすこし大きいスクリプトで"ハッシュのリファレンスの配列を他のサブルーチンに渡す"ということを想定しており、これが解決できず先に進めない状態です。 アドバイス、解決法がわかったら教えていただけないでしょうか。

    • ベストアンサー
    • Perl
  • requireについて教えてください。

    こんにちは、require について教えてください。 require されるファイルの最終行は 1 を書くのが一般的ですが、 他の値を書くと何か問題があるのでしょうか? 以下の実験をしてみました。 -- require されるファイル array.pl -- #! usr/bin/perl -w use strinct; ['a','b','c',] -- 実行するスクリプト -- #! /usr/bin/perl use strict; my $array_ref = get_array_ref('array.pl'); print "$_n" foreach ( @{$array_ref} ); exit(); sub get_array_ref {   return eval {require $_[0]}; } -- 結果 -- a b c 結果はうまく行ったのですが、eval も含めてこの様な使い方は 間違っていませんでしょうか? よろしくお願いします。

  • ハッシュに保存した配列を取得する方法

    ハッシュに保存した配列を取り出すサンプルを2ケース作成したのですがいずれもうまくいきませんでした。 1ケース目は「value=sample2」、2ケース目は「value=5」と表示されてしまいました。 いずれも@array2の内容が表示されることを期待していたのですがどのように修正すればよろしいでしょうか? my @array1 = (0, 1, 2, 3, 4); my @array2 = (5, 6, 7, 8, 9); # 1ケース目_ハッシュを使用 my %total = ( sample1 => @array1, sample2 => @array2 ); # 結果表示1 my @res = %total{sample2}; for (my $i = 0; $i < @res; $i++) { print 'value=' . $res[$1] . "\n"; } # 2ケース目_ハッシュのリファレンスを使用 my $total2 = { sample1 => @array1, sample2 => @array2 }; # 結果表示2 my @res2 = $total2->{sample2}; for (my $i = 0; $i < @res2; $i++) { print 'value=' . $res2[$1] . "\n"; }

    • ベストアンサー
    • Perl
  • 配列の操作に関して

    perlプログラミング初心者です。 質問なのですが、ある配列array1に関して foreach(@array1){ ・・・・・・ } という操作をしています。この操作を@arrray2,@array3,@array4に関して、ループを使って行いたいのですがどのようにすればよいのでしょうか。配列の配列を作って @Array = qw/ @array1 @array2 @array3 @array4/; として foreach構文を使うと、@array1が展開されずに処理できませんし・・ 初歩的なことだと思いますがアドバイスお願いします。

    • ベストアンサー
    • Perl
  • 配列とハッシュの配列の要素を比較してファイルに書き出したい

    配列Aとハッシュの配列Bがあり、配列の内容をファイルに書き出そうとしています。このとき、パターンマッチをして、Aにしかない場合はAのデータを、Bにしかない場合はBを、両方にある場合は、Aをファイルに出力しようとしています。 以下のようなループのまわし方をしようとして、試行錯誤しましたが、うまい方法を思いつくことができませんでした。 ご教授いただければうれしいです。 while (defined $A[$i]) {  my ($name, $pass);  $j=0;  while (($name, $pass) = each(%{$B[$j]})){    if ($A[$i] =~ /$name/) {    }    $j++;  } $i++; }

    • ベストアンサー
    • Perl
  • 配列 各項目を$n倍するプログラムソース

    配列 @in=(10,20,30,40) がある、各項目を $n 倍するプログラムを作っていますが、 $n 倍出来ません。 以下、プログラムです。 #!/usr/bin/perl @in=(10,20,30,40) ; print"@inを"; print"何倍しますか?:"; chomp($n=<>); foreach $ni_tall (@in) { $n *= $ni_tall; } $ave = $n * @in; print "結果: $ave\n"; print "結果: $ni_tall\n"; print "結果: $n\n"; print "結果: @in\n"; ___実行結果___ 10,20,30,40を何倍しますか?:7 結果:6720000 結果: 結果: 1680000 結果: 10 20 30 40 となってしまいます。 例えば、 :2 結果:20,40,60,80 としたいのですが、 分かりません。 分かる方いましたら、教えて頂けると助かります。 よろしくお願いします。

    • ベストアンサー
    • Perl

専門家に質問してみよう