LoginSignup
18
22

More than 5 years have passed since last update.

Perlのsortの基本的なやつ

Last updated at Posted at 2014-05-30

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系以降で動作すると思います。
それより前のバージョンでは、リファレンスを使うなら、値の渡し方を変えないとダメなような。

18
22
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
22