Perlのsortの基本的なやつ

## Perlでソートしたい

`sort`関係がよくあやふやになるので、メモです。


### 普通の配列のソート

これは特に迷うことないです。

```pl
my @arr = (3, 2, 8, 6);
foreach ( sort { $a <=> $b } @arr ){
	print $_, "\n";
}
```

```pl:結果
2
3
6
8
```


### ハッシュの配列のソート

これも割と普通です。

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

```pl:結果
test2:2
test1:3
test4:6
test3:8
```


### ハッシュのソート

配列じゃなくてもソートして取り出せます。

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

```pl:結果
test2:2
test1:3
test4:6
test3:8
```


### ハッシュのハッシュのソート

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

```pl:結果
test2:2
test1:3
test4:6
test3:8
```


### ハッシュのハッシュのハッシュのソート

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

```pl:結果
test2:2
test1:3
test4:6
test3:8
```


### 配列のハッシュのソート

この辺から（自分的には）わかりづらくなってきます。

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

```pl:結果
test2:2
test1:3
test4:6
test3:8
```

### ハッシュの配列のハッシュのソート

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

```pl:結果
test2:2
test1:3
test4:6
test3:8
```


### ハッシュの配列（中身順不同）のハッシュのソート

配列のどこかに`value`というキーを持ったハッシュが存在して、それを基準にソートしたい場合。
結構ぐちゃぐちゃです。
きっともっといい方法があるような気がします。

```pl
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}} とします。
}
```

```pl:結果
test2:2
test1:3
test4:6
test3:8
```


## 思ったこと。

後半は特に、そもそものデータの構造に何か問題がある気がします。
とはいえ、外部データを使用する際などはこんな作業も必要なこともあるかな、と思いました。


## ちなみに
Perl 5.14系以降で動作すると思います。
それより前のバージョンでは、リファレンスを使うなら、値の渡し方を変えないとダメなような。