Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
perl对日期时间字符串的多个arryrefs进行排序_Perl_Sorting_Arrayref - Fatal编程技术网

perl对日期时间字符串的多个arryrefs进行排序

perl对日期时间字符串的多个arryrefs进行排序,perl,sorting,arrayref,Perl,Sorting,Arrayref,我想对arrayref%results(时间字符串,从旧到新)进行排序,它有多个键,但我只发布了一个键来显示它的外观: 'Ende Monatswechsel P-Konten' => [ '17.02.2018 05:17:39', '14.02.2018 04:28:11',

我想对arrayref%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',
                                  ]
我期待着:

    '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[$\u,sort{$a$b}@{$results{$\u}],key%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;
            }
}

类似这样的方法会奏效:

#!/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;
更新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;

拆分字符串并比较部分适用于对多种类型的“多部分”值进行排序,但是,由于您处理的是日期时间,因此可以使用核心模块
Time::Piece
将字符串转换为可以使用
操作符进行比较的日期时间对象

Time::Piece
提供了
strtime
方法,该方法使用格式字符串将日期字符串解析为
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') 
}
使用v5.10;
严格使用
使用警告;
使用时间::件;
我的@VAL=(
'17.02.2018 05:17:39',
'14.02.2018 04:28:11',
'23.02.2018 03:17:17',
'22.02.2018 03:39:20',
);
表示排序{dt($a)dt($b)}@vals;
###
次级dt{
我的$str=班次;
返回时间::工件->strTime($str,'%e.%m.%Y%H:%m:%S')
}

我现在实际上使用了Dave的方法(因为我没有安装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=();
my@array;
我的@sorted;
我的%a是f\n;
对于我的$key(key%结果){
对于我的$i(0..$#{$results{$key}}){
推送@array,$results{$key}[$i];
}
@排序{
我的@a=split/[\.]/,$a;
my@b=split/[\.]/,$b;
返回(
$a[2]$b[2]或
$a[1]$b[1]或
$a[0]$b[0]或
$a[3]cmp$b[3]
);
}@数组;
$aref_n{$key}=[@sorted];
@数组=();

}

定义“它不起作用”的含义;它怎么不起作用?你得到了什么样的输出?你期望得到什么样的输出?我期望:
'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',                                   ]
通常的方法是拆分字符串并比较各个部分。更好的方法是强制上游系统将日期输出为
YYYY-mm-dd HH:mm:SS
。然后您可以使用字符串比较。@Unsal:好的,现在我完全糊涂了。您最初的帖子强烈暗示您想要对存储在中的数组进行排序散列。这就是我的代码所做的。现在您已经发布了在散列中构建数组的代码(并且,据我所见,以正确的顺序构建它)。所以,我真的不知道你在问什么。@Dave:很抱歉没有把它弄得足够精确。是的,这是一个arrayref,你看到的只是输出的一部分。乍一看,它看起来已经排序了,但我有>100个值,其中日期在该arrayref中未排序。嗨,Dave,谢谢你的回答。我不确定schwart是如何排序的zian转换应该在这里工作,因为我有固定长度的日期字符串。顺便说一句,您的建议不起作用,它返回:
$VAR1=['17.02.2018 05:17:39','23.02.2018 03:17:17','14.02.2018 04:28:11','22.02.2018 03:39:20'];
@Unsal:看起来你不是在运行我的实际代码。我的代码返回一个数组,但你正在转储一个数组引用。@Unsal:我的代码将数组引用(
$data
)作为输入并返回一个数组(
@sorted
)。编辑您的问题以添加代码的当前状态,我来看看。在我的代码中,我将时间戳推入哈希(%results),如下所示:
push@{$results{$action},$timestamp;
但我不能将您的代码与我的arrayref一起使用。如果它真的只是几个元素,这是很好的,但对于任何更长的列表,我建议实际使用Schwartzian变换,因为
Time::Piece
并没有那么便宜。它仍然会很贵,但要少得多。公平点说来,我个人会我会选择简洁易读而不是优化,除非速度至关重要。我同意。我只是想指出,
Time::Piece
有点贵。(这让我很惊讶;有一次我不得不放弃它,转而手动解析,因为它增加了太多的开销。但那段代码需要处理很多。)我也很惊讶,因为它是一个核心模块,我假设它是一个快速的C实现,但感谢您的洞察力。然后,施瓦茨变换的一个特点是效率(因为在短路之前只比较它需要什么)抱歉,我可能没有说清楚:我发现模块太慢(对于耗时代码中的长列表),没有转换;没有排序,只是
time::Piece
花费的时间比我预期的要长。(因此,我在这里提到了转换,因为排序
TP->strtime
对每个比较都运行一次;转换对每个列表元素运行一次,然后缓存的对象仅用于比较。)
$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'
                                           ]
        };
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') 
}
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=();