Что делает ваш код
foreach my $key (
sort { $hashofarrays{$a}[0] cmp $hashofarrays{$b}[0] }
keys %hashofarrays
) {
print "$key =>", join (", ", @{$hashofarrays{$key}}), "\n";
}
При этом используются ключи хэша для сортировки элементов хэша по первому элементу ссылки на массив, который находится внутри этого ключа в хэше. Он использует cmp
, что является ascii-betical сортировкой, а не числовой. Это означает, что 10
предшествует 2
, потому что 1
является символом ниже, чем 2
.
Для сортировки по дате это имеет смысл. Но поскольку ваш формат даты не соответствует двум цифрам для месяцев и дней, он не будет сортироваться должным образом.
18/5/1 # sorted last
18/10/1 # sorted first
Для этих двух дат первая из дат октября будет отсортирована первой, что неверно.
Что нужно сделать вместо этого
Если вы не можете очистить входные данные, вам нужно обработать их, чтобы выяснить значение за датой, а не полагаться на представление для сортировки. Синтаксический анализ дат - это его собственная проблема, и мы будем использовать Time :: Piece , чтобы сделать это, что уже некоторое время было в ядре Perl.
Мы могли бы сделать это так: псевдокод:
sort { parse($a) <=> parse($b) } ...
Это сработало бы, но было бы медленно, особенно для большего количества записей, потому что оно анализирует дату при каждом сравнении. Если вы не знаете, как работает внутренняя сортировка, она сравнивает значения друг с другом, возможно, меняет положение двух значений и повторяет.
Есть способ сделать это более эффективным, но это немного сложнее.
use strict;
use warnings;
use Time::Piece;
my %values = ( 'joe tribiani' => [ '16/3/28 13:42', 'XII', '99.93%' ],
'Ross' => [ '16/3/28 13:43', 'XII', '76.93%' ],
'sue grace' => [ '11/7/5 12:07', 'VI', '77.58%' ], );
my @sorted_keys = map { $_->[1] }
sort { $a->[0] <=> $b->[0] }
map {
[ Time::Piece->strptime( $values{$_}->[0], '%y/%m/%d %H:%M' )->epoch, $_ ]
}
keys %values;
use Data::Dumper;
print Dumper @sorted_keys;
Это называется преобразованием Шварца . По сути, он обрабатывает значения один раз, помещает их в другую ссылку на массив вместе с действительными значениями, которые сортируются. Затем он сортирует предварительно обработанные значения и возвращает их обратно.
Это гораздо эффективнее, и из-за синтаксического анализа он будет работать со всеми датами, которые могут отображаться в ваших значениях, без неправильной сортировки.
Обратите внимание, что нам нужно использовать оператор числового сравнения <=>
сейчас, потому что мы сортируем значения epoch , которые являются просто числами (много секунд из 1970-01-01T00:00:00
).