Perl сортирует несколько строк строк времени и даты - PullRequest
0 голосов
/ 26 ноября 2018

Я хочу отсортировать массивref% результатов (временные строки, от старого к новому), он имеет несколько ключей, но я только что опубликовал один ключ, чтобы показать, как он выглядит:

'Ende Monatswechsel P-Konten' => [
                                         '17.02.2018 05:17:39',
                                         '14.02.2018 04:28:11',
                                         '23.02.2018 03:17:17',
                                         '22.02.2018 03:39:20',
                                  ]

Яожидая:

    'Ende Monatswechsel P-Konten' => [
                                         '14.02.2018 04:28:11',
                                         '17.02.2018 05:17:39',
                                         '22.02.2018 03:39:20',
                                         '23.02.2018 03:17:17',
                                  ]

Кто-нибудь знает, как это сделать?Я пытался:

my $columns = map [ $_, sort{$a <=> $b} @{ $results{$_} } ], keys %results;

, но это не работает.Заранее спасибо.

Мой код выглядит так:

while(my $line=<F>) {
    #- Info: 19.02.2018 00:01:01 --- Start Tageswechsel-CoBa ---
    #- Info: 27.11.2018 04:16:42 --- Ende Tageswechsel-CoBa ---
            if ($line=~ /(\d\d\.\d\d\.\d\d\d\d \d\d:\d\d:\d\d) --- (.+? Tageswechsel-CoBa) -.*\s*$/)
            {
                    ($timestamp, $action) = ($1,$2);
            }
            if ( !defined $filter{$action}{$timestamp} ) {
                    push @{$results{$action}}, $timestamp;
                    $filter{$action}{$timestamp} = 1;
            }
}

print Dumper(\%results) вывод:

'Start Tageswechsel-CoBa' => [
                                '17.02.2018 05:12:13',
                                '20.02.2018 04:23:16',
                                '22.02.2018 03:12:46',
                                '23.02.2018 03:34:28',
                                '27.02.2018 03:41:25',
                                '02.03.2018 03:32:26',
            ],
'Ende Tageswechsel-CoBa' => [
                                    '17.02.2018 05:20:01',
                                    '19.02.2018 06:01:02',
                                    '20.02.2018 04:29:44',
                                    '22.02.2018 03:19:04',
                                    '23.02.2018 03:40:52',
                                    '26.02.2018 06:01:26',
            ]
            };

Ответы [ 3 ]

0 голосов
/ 28 ноября 2018

Разделение строк и сравнение частей подходит для сортировки многих типов «многочастных» значений, однако, поскольку вы имеете дело с datetime, вы можете использовать основной модуль Time::Piece, чтобы превратить строки в объекты datetime, которые можно сравниватьиспользование оператора <=>.

Time::Piece предоставляет метод strptime, который анализирует строку даты в объекте Time::Piece с использованием строки формата.Time::Piece объекты можно сравнивать с помощью операторов численного сравнения.

use v5.10;
use strict
use warnings;
use Time::Piece;

my @vals = (
    '17.02.2018 05:17:39',
    '14.02.2018 04:28:11',
    '23.02.2018 03:17:17',
    '22.02.2018 03:39:20',
);

say for sort {dt($a) <=> dt($b)} @vals;

###

sub dt {
    my $str = shift;
    return Time::Piece->strptime($str,'%e.%m.%Y %H:%M:%S') 
}
0 голосов
/ 28 ноября 2018

Я фактически использовал подход Дейва сейчас (поскольку у меня не установлен модуль Time :: Piece) немного по-другому, но он работает сейчас, хотя не уверен насчет эффективности:

my @array;
my @sorted;
my %aref_n;

for my $key ( keys %results ) {
    for my $i (0..$#{ $results{$key} }) {
            push @array, $results{$key}[$i];
    }

    @sorted = sort {
            my @a = split /[\. ]/, $a;
            my @b = split /[\. ]/, $b;
            return (
                    $a[2] <=> $b[2] or
                    $a[1] <=> $b[1] or
                    $a[0] <=> $b[0] or
                    $a[3] cmp $b[3]
                    );
            } @array;

    $aref_n{$key} = [ @sorted ];
    @array=();

}

0 голосов
/ 26 ноября 2018

Примерно так будет работать:

#!/usr/bin/perl

use strict;
use warnings;
use feature 'say';

use Data::Dumper;

my $data = [
  '17.02.2018 05:17:39',
  '14.02.2018 04:28:11',
  '23.02.2018 03:17:17',
  '22.02.2018 03:39:20',
];

my @sorted = sort {
  my @a = split /[\. ]/, $a;
  my @b = split /[\. ]/, $b;
  return (
    $a[2] <=> $b[2] or  # year
    $a[1] <=> $b[1] or  # month
    $a[0] <=> $b[0] or  # day of month
    $a[3] cmp $b[3]     # time
  );
} @$data;

say Dumper @sorted;

Я разбиваю каждое значение на куски, а затем сортирую их по наибольшему куску на наименьшее.Обратите внимание, что поскольку время является строкой, а не числом, я использую cmp вместо <=>.

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

Но лучшим решением для этого было бы сначала получить сортируемую временную метку.Если бы ваши даты были YYYY.MM.DD HH:MM:SS, вы могли бы просто выполнить простую сортировку строк.

Обновление: Мой вывод

$ perl sortdate
$VAR1 = '14.02.2018 04:28:11';
$VAR2 = '17.02.2018 05:17:39';
$VAR3 = '22.02.2018 03:39:20';
$VAR4 = '23.02.2018 03:17:17';

Обновление 2: Я отредактировал свой код, чтобы сделать его более похожим на ваш пример.Надеюсь, это поможет.

#!/usr/bin/perl

use strict;
use warnings;
use feature 'say';

use Data::Dumper;

my %results = (
  'Ende Monatswechsel P-Konten' => [
    '17.02.2018 05:17:39',
    '14.02.2018 04:28:11',
    '23.02.2018 03:17:17',
    '22.02.2018 03:39:20',
  ]
);

foreach my $k (keys %results) {
  my @sorted = sort {
    my @a = split /[\. ]/, $a;
    my @b = split /[\. ]/, $b;
    return (
      $a[2] <=> $b[2] or  # year
      $a[1] <=> $b[1] or  # month
      $a[0] <=> $b[0] or  # day of month
      $a[3] <=> $b[3]     # time
    );
  } @{ $results{$k} };

  $results{$k} = \@sorted;
}

say Dumper \%results;

И вывод ...

$VAR1 = {
          'Ende Monatswechsel P-Konten' => [
                                             '14.02.2018 04:28:11',
                                             '17.02.2018 05:17:39',
                                             '22.02.2018 03:39:20',
                                             '23.02.2018 03:17:17'
                                           ]
        };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...