Perlでソートしたい
sort
関係がよくあやふやになるので、メモです。
普通の配列のソート
これは特に迷うことないです。
my @arr = (3, 2, 8, 6);
foreach ( sort { $a <=> $b } @arr ){
print $_, "\n";
}
結果
2
3
6
8
ハッシュの配列のソート
これも割と普通です。
my $hash_array_ref = [
{ name => 'test1', value => 3 },
{ name => 'test2', value => 2 },
{ name => 'test3', value => 8 },
{ name => 'test4', value => 6 },
];
foreach ( sort { $a->{value} <=> $b->{value} } @$hash_array_ref ){
print $_->{name}, ':', $_->{value}, "\n";
}
結果
test2:2
test1:3
test4:6
test3:8
ハッシュのソート
配列じゃなくてもソートして取り出せます。
my $hash_ref = {
test1 => 3,
test2 => 2,
test3 => 8,
test4 => 6,
};
foreach ( sort { $hash_ref->{$a} <=> $hash_ref->{$b} } keys $hash_ref ){
print $_, ':', $hash_ref->{$_}, "\n";
}
結果
test2:2
test1:3
test4:6
test3:8
ハッシュのハッシュのソート
my $hash_hash_ref = {
test1 => { value => 3, hoge => 'fuga' },
test2 => { value => 2, hoge => 'fuga' },
test3 => { value => 8, hoge => 'fuga' },
test4 => { value => 6, hoge => 'fuga' },
};
foreach ( sort { $hash_hash_ref->{$a}->{value} <=> $hash_hash_ref->{$b}->{value} } keys $hash_hash_ref ){
print $_, ':', $hash_hash_ref->{$_}->{value}, "\n";
}
結果
test2:2
test1:3
test4:6
test3:8
ハッシュのハッシュのハッシュのソート
my $hash_hash_hash_ref = {
test1 => { hoge => { value => 3, fuga => 'hogera' } },
test2 => { hoge => { value => 2, fuga => 'hogera' } },
test3 => { hoge => { value => 8, fuga => 'hogera' } },
test4 => { hoge => { value => 6, fuga => 'hogera' } },
};
print "\nhash hash hash ref\n";
foreach ( sort { $hash_hash_hash_ref->{$a}->{hoge}->{value} <=> $hash_hash_hash_ref->{$b}->{hoge}->{value} } keys $hash_hash_hash_ref ){
print $_, ':', $hash_hash_hash_ref->{$_}->{hoge}->{value}, "\n";
}
結果
test2:2
test1:3
test4:6
test3:8
配列のハッシュのソート
この辺から(自分的には)わかりづらくなってきます。
my $array_hash_ref = {
test1 => [3, 'hoge'],
test2 => [2, 'hoge'],
test3 => [8, 'hoge'],
test4 => [6, 'hoge'],
};
foreach ( sort { $array_hash_ref->{$a}->[0] <=> $array_hash_ref->{$b}->[0] } keys $array_hash_ref ){
print $_, ':', $array_hash_ref->{$_}->[0], "\n";
}
結果
test2:2
test1:3
test4:6
test3:8
ハッシュの配列のハッシュのソート
my $hash_array_hash_ref = {
test1 => [ { value => 3 }, { fuga => 'hogera' } ],
test2 => [ { value => 2 }, { fuga => 'hogera' } ],
test3 => [ { value => 8 }, { fuga => 'hogera' } ],
test4 => [ { value => 6 }, { fuga => 'hogera' } ],
};
foreach ( sort { $hash_array_hash_ref->{$a}->[0]->{value} <=> $hash_array_hash_ref->{$b}->[0]->{value} } keys $hash_array_hash_ref ){
print $_, ':', $hash_array_hash_ref->{$_}->[0]->{value}, "\n";
}
結果
test2:2
test1:3
test4:6
test3:8
ハッシュの配列(中身順不同)のハッシュのソート
配列のどこかにvalue
というキーを持ったハッシュが存在して、それを基準にソートしたい場合。
結構ぐちゃぐちゃです。
きっともっといい方法があるような気がします。
my $hash_array_hash_ref2 = {
test1 => [ { value => 3 }, { fuga => 'hogera' } ],
test2 => [ { fuga => 'hogera' }, { value => 2 } ],
test3 => [ { value => 8 }, { fuga => 'hogera' } ],
test4 => [ { fuga => 'hogera' }, { value => 6 } ],
};
foreach ( sort { $a->{value} <=> $b->{value} } map { my @tmp = grep { $_->{value} } @{$hash_array_hash_ref->{$_}}; { key => $_, value => $tmp[0]->{value} }; } keys $hash_array_hash_ref2 ){
print $_->{key}, ':', $_->{value}, "\n";
# $_ は key と value をセットにしたハッシュの配列なので、元の変数にアクセスしたい場合は
# $hash_array_hash_ref2->{$_->{key}} とします。
}
結果
test2:2
test1:3
test4:6
test3:8
思ったこと。
後半は特に、そもそものデータの構造に何か問題がある気がします。
とはいえ、外部データを使用する際などはこんな作業も必要なこともあるかな、と思いました。
ちなみに
Perl 5.14系以降で動作すると思います。
それより前のバージョンでは、リファレンスを使うなら、値の渡し方を変えないとダメなような。