Из твоего вопроса мне неясно, как ты на самом деле хочешь разобраться и как ты привел примеры.Я не могу обнаружить какой-либо порядок в примере вашего ожидаемого порядка сортировки.Вероятное решение находится внизу.
Позвольте мне уточнить:
Учитывая текстовый файл "ts" со следующим содержанием (ваш пример):
> cat ts
21:01:2011 16:51:09
21:01:2011 16:49:54
26:01:2011 11:02:55
26:01:2011 11:01:40
05:04:2011 11:51:13
05:04:2011 11:51:13
05:04:2011 11:48:37
05:04:2011 11:48:37
СтандартСортировка приводит к следующему выводу:
> perl -e '@a = <>; print sort @a' ts
05:04:2011 11:48:37
05:04:2011 11:48:37
05:04:2011 11:51:13
05:04:2011 11:51:13
21:01:2011 16:49:54
21:01:2011 16:51:09
26:01:2011 11:01:40
26:01:2011 11:02:55
В то время как предложенная вами сортировка по убыванию чисел производит следующий порядок:
> perl -e '@a = <>; print sort { $b <=> $a } @a' ts
26:01:2011 11:02:55
26:01:2011 11:01:40
21:01:2011 16:51:09
21:01:2011 16:49:54
05:04:2011 11:51:13
05:04:2011 11:51:13
05:04:2011 11:48:37
05:04:2011 11:48:37
Чтобы уточнить числовую сортировку: оператор космического корабля <=> обеспечиваетчисленная интерпретация двух его операндов.Таким образом, строки $ a и $ b, каждая из которых содержит дату и время, интерпретируются так, как если бы они были числами.Для этого perl в этом примере извлекает дату и останавливается на первом «:».Вот почему время и даже месяц и год полностью игнорируются, и мы сортируем только по дню месяца в порядке убывания.
Наконец, если вы действительно хотите выполнить обратную сортировку по дате, тогда времяи нужно сохранить формат, который вы можете использовать этот код:
> perl -e '@a = <>; sub dmyt2ymdt { my $dmyt=shift; $ymdt=join(q(), (split(/[:\s]+/,$dmyt))[2,1,0,3,4,5])} print sort { dmyt2ymdt($b) <=> dmyt2ymdt($a) } @a' ts
05:04:2011 11:51:13
05:04:2011 11:51:13
05:04:2011 11:48:37
05:04:2011 11:48:37
26:01:2011 11:02:55
26:01:2011 11:01:40
21:01:2011 16:51:09
21:01:2011 16:49:54
Вот лучшая отформатированная версия (которую я не тестировал):
sub dmyt2ymdt {
my $dmyt = shift;
my ($day, $mon, $year, $h, $m, $s) = split(/[:\s]+/, $dmyt);
return join('', $year, $mon, $day, $h, $m, $s);
}
Эта функция сортировки
sort { dmyt2ymdt($b) <=> dmyt2ymdt($a) }
затем довольно часто вызывает вышеуказанного помощника.В вашем примере у нас есть 8 записей в списке для сортировки, и функция вызывается 24 раза.Так что это неэффективно.Но для небольших списков до пары сотен или даже тысяч записей это может быть хорошо для вас.Если у вас большие списки, вы должны выполнить преобразование формата только один раз, но это все еще стоит памяти.Таким образом, для больших списков вам нужно соотносить память с временем выполнения, как это часто бывает.
Если производительность является критерием оптимизации, вы можете выполнить преобразование на лету, как было прокомментировано и показано в других ответах.и комментарии как это:
sort { $b <=> $a } map { dmyt2ymdt($_) } @a
.. для моего примера выше.Теперь вы делаете преобразование только один раз для каждого элемента.Тем не менее, мы должны держать временный список в памяти.Я не совсем уверен, насколько хорошо Perl может оптимизировать вышеупомянутую конструкцию.Можно подумать, что легче оптимизировать следующее:
reverse sort map { dmyt2ymdt($_) } @a
, что также будет работать для тестового набора.По умолчанию сортировка возвращается к сравнению строк, которое совпадает с числовым сравнением строк одинаковой длины, которые не используют пробелы в тех местах, где другие строки имеют цифры.
Надеюсь, это поможет!