アプリ版:「スタンプのみでお礼する」機能のリリースについて

タイトルが意味不明で申し訳ありません。
二つの配列があるとします。
片方には文字列、もう片方には数値が記録されているもので、最大添え字は同じです。
この数値の大きい順に並べ替えを行いたいのですが、
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;
}
}

A 回答 (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]);
}
}
}
    • good
    • 0
この回答へのお礼

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

お礼日時:2007/03/29 18:36

最初からハッシュの配列にしておけばよかったんだけどね. 今さらしょうがないってことなんだろうけど.


で, @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;
    • good
    • 0
この回答へのお礼

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

お礼日時:2007/03/29 18:40

まあやり方は複数ありますし、きっと色々な人が


それぞれのやり方で書いてくれると思いますが一例として。

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";
}

こんな感じで。
自前でソートルーチン組むのはよっぽどのことがない限り
止めておいた方が無難だと思います。
    • good
    • 0
この回答へのお礼

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

お礼日時:2007/03/29 18:38

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!