- ベストアンサー
配列をソートさせたとき、もう一方の配列も同じようにソートさせたい
タイトルが意味不明で申し訳ありません。 二つの配列があるとします。 片方には文字列、もう片方には数値が記録されているもので、最大添え字は同じです。 この数値の大きい順に並べ替えを行いたいのですが、 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; } }
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
選択法と交換法の整列アルゴリズムを混同していると思います。 基本選択法(最大値法)ならこんな比較なので。 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]); } } }
その他の回答 (2)
- Tacosan
- ベストアンサー率23% (3656/15482)
最初からハッシュの配列にしておけばよかったんだけどね. 今さらしょうがないってことなんだろうけど. で, @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;
お礼
@filelistはディレクトリから読み込んだファイル名、@countはさらにそのファイルから読み込んだ数値群だったので、はじめからハッシュにできなかったんです(できるかもしれないけど、方法が…) そんなわけで配列2つでのリンクソートに頭を悩ませていました。 ご回答ありがとうございました。
- sakusaker7
- ベストアンサー率62% (800/1280)
まあやり方は複数ありますし、きっと色々な人が それぞれのやり方で書いてくれると思いますが一例として。 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"; } こんな感じで。 自前でソートルーチン組むのはよっぽどのことがない限り 止めておいた方が無難だと思います。
お礼
ご回答ありがとうございました。 ただ、私には少しむずかしかったようです
お礼
ありがとうございます! プログラムも動き、ソートを理解することもできました。