• ベストアンサー

配列をソートさせたとき、もう一方の配列も同じようにソートさせたい

タイトルが意味不明で申し訳ありません。 二つの配列があるとします。 片方には文字列、もう片方には数値が記録されているもので、最大添え字は同じです。 この数値の大きい順に並べ替えを行いたいのですが、 name[0]とcount[0] name[1]とcount[1] ・ ・ をペアで並べ替えたいのですが、その方法が分かりません。 sort関数を使うとどうしても片方のみしかソートできないし、バブルソートを用いて試みましたが、どうも並び替えられません。 連想配列を使う考えもありましたが、2つの配列をどうやって一つのハッシュに格納すればいいか分からず断念しました。 バブルソートの方にバグがあるのかもしれませんが、何か方法があればご教授いただけると幸いです。 よろしくお願いします。 バブルソート部分のソース(配列は@filelistと@countを使用) # ソート処理 for($i=0;$i<$#filelist;$i++){ for($j=0;$i<$j;$j++){ if($count[$i]<$count[$i+1]){ $tmp=$count[$i]; $count[$i]=$count[$i+1]; $count[$i+1]=$tmp; $tmp=$filelist[$i]; $filelist[$i]=$filelist[$i+1]; $filelist[$i+1]=$tmp; $k=$j; } $i=$k; } }

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

  • ベストアンサー
  • jjon-com
  • ベストアンサー率61% (1599/2592)
回答No.1

選択法と交換法の整列アルゴリズムを混同していると思います。 基本選択法(最大値法)ならこんな比較なので。 1巡目: 0-1, 0-2, 0-3, 0-4 2巡目: 1-2, 1-3, 1-4 3巡目: 2-3, 2-4 4巡目: 3-4 for ($i=0; $i<$#count; $i++){ for ($j=$i+1; $j<=$#count; $j++){ if ($count[$i] < $count[$j]) { ($count[$i], $count[$j]) = ($count[$j], $count[$i]); ($filelist[$i], $filelist[$j]) = ($filelist[$j], $filelist[$i]); } } } 隣接交換法(バブルソート)ならこんな比較なので。 1巡目: 0-1, 1-2, 2-3, 3-4 2巡目: 0-1, 1-2, 2-3 3巡目: 0-1, 1-2 4巡目: 0-1 for ($i=$#count; $i>0; $i--){ for ($j=0; $j<$i; $j++){ if ($count[$j] < $count[$j+1]) { ($count[$j], $count[$j+1]) = ($count[$j+1], $count[$j]); ($filelist[$j], $filelist[$j+1]) = ($filelist[$j+1], $filelist[$j]); } } }

gottyato
質問者

お礼

ありがとうございます! プログラムも動き、ソートを理解することもできました。

その他の回答 (2)

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

最初からハッシュの配列にしておけばよかったんだけどね. 今さらしょうがないってことなんだろうけど. で, @count の昇順にソートしつつ @name をそれに合わせて動かすならこんな感じかな: my @data; for my $i (0 .. (#$count-1)) { push @data, { count => $count[$i], name => $name[$i] }; } my @sorted = sort { $a->{count} <=> $b->{count}; } @data; @count = map { $_->{count}; } @sorted; @name = map { $_->{name}; } @sorted;

gottyato
質問者

お礼

@filelistはディレクトリから読み込んだファイル名、@countはさらにそのファイルから読み込んだ数値群だったので、はじめからハッシュにできなかったんです(できるかもしれないけど、方法が…) そんなわけで配列2つでのリンクソートに頭を悩ませていました。 ご回答ありがとうございました。

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.2

まあやり方は複数ありますし、きっと色々な人が それぞれのやり方で書いてくれると思いますが一例として。 use strict; use warnings; my @ary_count = (6116, 14720, 10515, 7954, 26908, 1694); my @ary_name = qw( aaaa bbbb cccc xxxx yyyy zzzz ); print "count=$ary_count[$_], name=$ary_name[$_]\n" for 0 .. $#ary_count; print "#####\n"; my @sorted_idx = sort {$ary_count[$a] <=> $ary_count[$b]} 0 .. $#ary_count; print "count=$ary_count[$_], name=$ary_name[$_]\n" for @sorted_idx; 実行結果: count=6116, name=aaaa count=14720, name=bbbb count=10515, name=cccc count=7954, name=xxxx count=26908, name=yyyy count=1694, name=zzzz ##### count=1694, name=zzzz count=6116, name=aaaa count=7954, name=xxxx count=10515, name=cccc count=14720, name=bbbb count=26908, name=yyyy 添え字をcountの値でソートして配列に収め、 それを使って順に取り出します。 上記の例では表示にしか使っていませんが実際に配列を並べ替えたいのなら my @ary_count_sorted = @ary_count[@sorted_idx]; my @ary_name_sorted = @ary_name[@sorted_idx]; foreach my $idx (0 ..$#ary_count_sorted) { my $name; my $count; $name = $ary_name_sorted[$idx]; $count = $ary_count_sorted[$idx]; print "$idx:$count:$name\n"; } こんな感じで。 自前でソートルーチン組むのはよっぽどのことがない限り 止めておいた方が無難だと思います。

gottyato
質問者

お礼

ご回答ありがとうございました。 ただ、私には少しむずかしかったようです

関連するQ&A

専門家に質問してみよう