Сортировка числовых ключей хеша, разделенных дефисом
У меня есть такой хэш
my %hash = (
'2011-49' => 'data1',
'2011-100' => 'data2',
'2009-22' => 'data3',
'2011-11' => 'data4',
'4323' => 'data5',
'2354' => 'data6',
'423532-2' => 'data7'
);
Как отсортировать ключи хеша так, чтобы они сортировались на основе первого числа, а затем второго числа, показывающего следующий вывод.
my %hash = (
'2009-22' => 'data3',
'2011-11' => 'data4',
'2011-49' => 'data1',
'2011-100' => 'data2',
'2354' => 'data6',
'4323' => 'data5',
'423532-2' => 'data7'
);
Я нажал все ключи в массиве и отсортировал с помощьюSort::Naturally qw(nsort ncmp)
Но это не работает.
2 ответа
Как я сказал в комментариях, вы не можете сортировать хэш, потому что хэш не сохраняет порядок своих ключей. Вы можете, однако, отсортировать ключи и сохранить их во что-то, что сохраняет порядок, например, массив. Для этой цели мы можем использовать преобразование Шварца:
my @sorted_keys = map $_->[0], # 3)
sort { $a->[1] <=> $b->[1] ||
$a->[2] <=> $b->[2] } # 2)
map { [ $_, /(\d+)/g ] } keys %hash; # 1)
С конца мы 1) сначала сохраняем исходную строку, плюс первое и второе число внутри анонимного массива ref. В результате получается список ссылок на массивы - кеш, который мы 2) передаем sort
где они отсортированы по первому номеру, а если они одинаковые - по второму. Это достигается с помощью ||
внутри sort
кодовый блок. Наконец, мы 3) восстановить исходную строку и отменить массив ссылок.
Вы уже получили хороший ответ, но подумали, что я взвеслю Sort:: Versions. Это, кажется, обрабатывает такие операции немного лучше, чем Sort:: Naturally:
use warnings;
use strict;
use Sort::Versions;
my %hash = (
'2011-49' => 'data1',
'2011-100' => 'data2',
'2009-22' => 'data3',
'2011-11' => 'data4',
'4323' => 'data5',
'2354' => 'data6',
'423532-2' => 'data7'
);
print "$_ => $hash{$_}\n" for ( sort{ versioncmp( $a, $b ) } keys %hash );
Это даст следующий результат:
2009-22 => data3
2011-11 => data4
2011-49 => data1
2011-100 => data2
2354 => data6
4323 => data5
423532-2 => data7
Конечно, вы можете хранить отсортированные значения в массиве, а не распечатывать их, но я подумал, что это может быть более понятным для вывода таким способом.