• ベストアンサー

静的ハッシュの配列のキーに対応する値の数の多さ順で表示させたい

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

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

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

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

この程度だと無意味だけど, シュワルツ変換 @sorted_keys = map { $_->[1]; } sort { $b->[0] <=> $a->[0] or $a->[1] <=> $b->[1]; } map { [ scalar @{$a{$_}}, $_ ]; } keys %a; とか, 同系統でハッシュを 1つ余計に使って my %tmp; while (my ($key, $val) = each %a) { $tmp{$key} = @{$a{$val}}; } @sorted_keys = sort { $tmp{$b} <=> $tmp{$a} or $a <=> $b; } keys %a; でもいいかな. (無名) 配列の長さごときに使うのはやりすぎな気もするけど. $# と scalar では 1つだけ値がずれますね>#2. まあ, 一律ずれるので影響はないんですが.

taku0
質問者

お礼

これまた素晴らしいご回答をご教授頂きありがとうございます。 シュワルツ変数について調べてみたのですが、簡単そうで何だか難しいですね。 で、調べていたら「続・初めてのPerl」がヒットしたのですが、ハッと思ったんです。今、まさにちょうど図書館で借りてるじゃん! で、試しに読むと、さかのぼってソートに関してから読み始めてみると、かなり分かりやすいですね。この調子で読み進めてゆきたいと思います。 借りても読まないと意味ないですが、今回の質問がそのきっかけになって良かったです。 多謝です。ありがとうございました。

その他の回答 (3)

  • g_p_
  • ベストアンサー率53% (28/52)
回答No.4

#2様、 >ところで、配列の添字数を取得するのにscalarを使用しているみたい >ですが、 @ を $# にするだけで取得できるのでは。 多分、スペースシップ演算子を使っている時点で、scalar は必要ありませんが、明示した方がわかりやすいと思ったまでです。 また、添字数を取得しているという意味ではありません。

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

ところで、配列の添字数を取得するのにscalarを使用しているみたい ですが、 @ を $# にするだけで取得できるのでは。

  • g_p_
  • ベストアンサー率53% (28/52)
回答No.1

こんにちは こんな感じですか? #! perl use strict; use Data::Dumper; my %hash = ( '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) ], ); my @sorted_keys = sort { scalar @{$hash{$b}} <=> scalar @{$hash{$a}} or $a <=> $b } keys %hash; print Dumper \@sorted_keys;

taku0
質問者

お礼

ご教授頂きありがとうございました。 Data::Dumperで表示させる事など思いもつきませんでした。 いや~素晴らしいです。 勉強になります。ありがとうございました。

関連するQ&A

  • ハッシュの中身の表示

    ハッシュの中身の確認ができなくて困っています。 下記のような実行文においてです。 当然、test の戻り値は、スカラーとハッシュです。ハッシュを戻すときには参照渡し記号の\もつけています。 my ($return_code, %hash_data) = test(); 表示しようとすると、 Hash(0x5b04) のような表示にしかなりません、、 (試した表示方法は、下記4つです。) (環境は、WindowsXP上での、ActivePerl-5.10.0.1004 です。) foreach $key ( keys( %Hash ) ) { print "キー値 : $key\n"; print "値 : $Hash{$key} \n " } while ( ( $key , $value ) = each %Hash ){ print "キー値 : $key\n"; print "値 : $value \n " ; } use Data::Dump qw(dump); print dump(\%hash); #print %display_test; 宜しくお願いします。

    • ベストアンサー
    • Perl
  • 2次元ハッシュ または 2次元配列をソートしたい

    2次元ハッシュのソートをしたいです。 ハッシュは2つのキーを使用していて、 1つ目のキーは文字列、2つ目のキーは数字(0からの連番)です。 ハッシュの中身は文字列が入っています。 これを次のような表に見立てて、特定の列でソートしたいのです。 hash['a']['0'], hash['a']['1'], ..., hash['a']['50'], hash['q']['0'], hash['q']['1'], ..., hash['q']['50'], hash['c']['0'], hash['c']['1'], ..., hash['c']['50'], ... hash['d']['0'], hash['d']['1'], ..., hash['d']['50'], 例えば 6列目の値によってソートするということです。 以下のようにソートしようとしましたが、うまくいきません。 my @sorthash = sort { $a->[6] <=> $b->[6] } @hash; 何かヒントがあれば教えてください。

    • ベストアンサー
    • Perl
  • 【javascript】ハッシュのキーをソートして取り出したい

    ハッシュのキーをソートして取り出したいです。 perlで表現すると、以下の様なかんじです。 foreach $key (sort keys %hash) { ... } そこで、prototype.jsを使って以下の様に書いてみました。 <html> <head> <script type="text/javascript" src="prototype.js"></script> </head> <body > <script > var table = {c:'C', b:'B', a:'A'}; $H(table).keys().sort().each(function(key){ alert(key + ' ' + table[key]); }); </script> </body> </html> 他に良い方法ありましたら、教えてください。

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

    ハッシュの配列を配列の数の多い順に表示する場合で配列の数が同じの場合の最初に表示される配列の数字につきまして この配列の数が同じである場合の表示順序を意図した順番にする事は可能でございますか? この意図した順番と申しますのは、小さい数字を先に表示するのではなく下記の@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
  • Ruby 2次元のハッシュ

    Rubyで2次元のハッシュを扱いたいです。 perlで書くと以下のような感じです。(最近perlに疎遠なので自信無いですが^^;) hash{$key1}{$key2}=$value; foreach $key1 (keys %hash){ foreach $key2 (keys %{$hash{$key1}}){ print "$hash{$key1}{$key2}\n"; } } Rubyだとどんな感じになりますか?

  • Perlでハッシュや配列で重複するキーについて

    ハッシュで重複するキーが値となるので、このハッシュはabdの3つのキーしか存在しないということでしょうか? %a = ('a'=>1, 'b'=>2, 'a'=>3, 'd'=>4); また、配列の場合はabadと4つ数になるということでしょうか? @a = ('a','b','a','d'); この場合配列で、重複する値を抽出するアルゴリズムが知りたいです。

    • ベストアンサー
    • 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
  • 動的ハッシュを作って取り出したいのですが・・・

    お世話になります。 フォームから送られてくるデータを動的に作ったハッシュで参照出来るように取り組んでるんですが、思ったように出来ず思い悩んでおります。 どうすれば、意図した形でデータを取り出すことが出来ますでしょうか my %FORM = ( 'd01' => 'あ', 'd02' => 'い', 'd03' => 'う', 'd04' => 'え', 'd05' => 'お', 'd06' => 'か', 'd07' => 'き', 'd08' => 'く', 'd09' => 'け', 'd10' => 'こ', ); for(sort { $FORM{$a} cmp $FORM{$b} } keys %FORM){ print "$_ = $FORM{$_} \n"; } $list="d01,d02,d03,d04,d05,d06,d07,d08,d09,d10,"; $i=-1; foreach (split/,/,$list){ $i++; $hash{$_}=$i; } for(sort { $hash{$a} <=> $hash{$b} } keys %hash){ print "$_ = $hash{$_} \n"; $view = ${"FORM$_"}; print "$view\n"; }; 最後のprint "$view\n";箇所で、 $list="d01,d02..." を split/,/,$list したので、 $FORM{d01} $FORM{d02} となるようにして、 「あ い う え お」と取り出したいのです。 ご教授のほど、よろしくお願い致します。

    • ベストアンサー
    • Perl
  • 当てはまらなかったら、エラー処理

    いい考えが思い付きません。 是非とも知恵を貸してください… CGIです。 フォームで入力された文字列とハッシュ内のキーを比較し、 一致すれば値を出力、すべてに当てはまらなかったらエラーを返すというのをやりたいのですが、 $value にフォームからの文字列が入っているとします。  $value = "1";  %hash = ("1" => "A", "2" => "B", "3" => "C"); if (&search()) {   last;  } else {   &error("一致しません"); } exit; #---------------------------------- sub search {  foreach $key(keys %hash) {   if ($key =~ /$value/) {    print "--$hash{$key}\n";   }  } } #---------------------------------- sub error {  print "error $_[0]\n"; } 結果は、 --A error 一致しません でした。 $value をキー以外にするとちゃんとエラーになるんですよ。 いい方法はないでしょうか?

    • ベストアンサー
    • Perl
  • ハッシュの値のグループ化について

    入門本に、次のような例題がありました(主要部分の抜粋です)。 @list = (20,25,24,32,28,20,28,24,20); #年齢リスト foreach $fld(@list){   $syukei{$fld}++; } print "<table><tr><th>年齢</th><th>人数</th></tr>\n"; foreach $key( reverse( sort( keys( %syukei ) ) ) ){   $cnt = $syukei{$key};   print"<tr><th>${key}才</th><th>${cnt}人</th></tr></table>\n"; これの実行結果は、@list の年齢を各年齢ごとにカウントして、表に各年齢が何人であるかを表示します。 ・$syukei{$fld}++; の部分は $ハッシュ名{'キー名'} でハッシュを作ろうとしているのだと思うのですが、++ がなぜ付くのか分かりません。 ・↑の考え方が合っているとしたら、$cnt = $syukei{$key} で右辺は $ハッシュ名{'キー名'} を表しているのだと思うのですが、左辺がスカラー値を求めている場合はキーの数を返すというルールがあるのでしょうか? 私の質問にこだわらず、分かりやすく全体の説明をして頂ければ助かります。

    • ベストアンサー
    • Perl

専門家に質問してみよう