Сортировка массива hashof строки даты и времени в Perl

Я пытался отсортировать даты на Perl. Строка datetime находится в хэше массивов. После долгих поисков в Google я использовал функцию сортировки Perl. К моему удивлению, это сработало. Мой код и ввод ниже:

use strict;
use warnings;

my %hashofarrays;

$hashofarrays{'joe tribiani'} = ['16/3/28 13:42','XII','99.93%'];
$hashofarrays{'Ross'} = ['16/3/28 13:43','XII','76.93%'];
$hashofarrays{'sue grace'} = ['11/7/5 12:07','VI','77.58%'];

foreach my $key (   sort{$hashofarrays{$a}[0] cmp $hashofarrays{$b}[0]}      keys %hashofarrays ) {
print "$key =>", join (", ", @{$hashofarrays{$key}}), "\n";
}

Я правильно это делаю? Если да, то как это работает?

Если это неправильно, что мне делать, чтобы отсортировать строку даты и времени?

В результате должны быть перечислены записи, отсортированные в порядке возрастания по дате и времени.

Формат даты и времени: «ГГ / ММ / ДД» или «ГГ / М / Д».

Мои данные:

joe tribiani, 16/3/28 13:42,XII,99.93%
Ross,16/3/28 13:43,XII,95.93%
sue grace,11/7/5 12:07,VI,77.58%

Мой исключенный вывод:

sue grace =>11/7/5 12:07, VI, 77.58%
joe tribiani =>16/3/28 13:42, XII, 99.93%
Ross =>16/3/28 13:43, XII, 76.93%

Какого результата вы ожидаете? Пожалуйста, редактировать свой вопрос и сообщите нам, каков ожидаемый заказ. В настоящий момент вы выполняете сортировку в формате ascii по первому элементу ссылки на массив. Если эта дата находится в порядке YY/M/D, это, вероятно, сработает.

simbabque 01.05.2018 18:17

Но, учитывая, что в некоторых случаях M - однозначное число, этого не произойдет :)

Sobrique 01.05.2018 18:24

Верно. Я бы сказал, проанализируйте значения для сортировки. Пришло время для некоторого преобразования Шварца.

simbabque 01.05.2018 18:26

Спасибо, я добавил свои данные и ожидаемый результат

D.Karthikeyan 01.05.2018 18:36

Можете ли вы также сказать нам, какой формат даты? Первое значение - год или день?

simbabque 01.05.2018 18:48

Первое значение - год. Формат даты: «ГГГГ / ММ / ДД» или «ГГГГ / М / Д».

D.Karthikeyan 01.05.2018 18:56

Спасибо за редактирование.

simbabque 01.05.2018 18:59
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
7
796
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Что делает ваш код

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

Для этих двух дат более поздняя октябрьская дата будет отсортирована первой, что неверно.

Что вам нужно делать вместо этого

Если вы не можете очистить входные данные, вам необходимо обработать их, чтобы вычислить значение за датой, вместо того, чтобы полагаться на представление для сортировки. Анализ дат - это отдельная проблема, и мы будем использовать для этого Время :: Кусок, который уже некоторое время присутствует в ядре 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;

Это называется Преобразование Шварца. По сути, он обрабатывает значения один раз, помещает их в другую ссылку на массив вместе с фактическими значениями, которые сортируются. Затем он сортирует предварительно обработанные значения и затем возвращает их.

Это намного эффективнее, и из-за синтаксического анализа он будет работать для всех дат, которые могут отображаться в ваших значениях, без их неправильной сортировки.

Обратите внимание, что сейчас нам нужно использовать оператор числового сравнения <=>, потому что мы сортируем значения эпоха, которые являются просто числами (много секунд из 1970-01-01T00:00:00).

Спасибо. Решение идеально подходит для моей проблемы.

D.Karthikeyan 01.05.2018 19:31

Другие вопросы по теме