基于一个项的值对Perl中的二维数组进行排序,但有异常

时间:2012-12-26 02:57:54

标签: perl sorting

目前,我正在使用二维数组,其中包含有关足球进球的信息。第一个数组中的每个项目都是一个数组,其中包含有关目标的不同信息。这个数组中的第二项是得分(1-90),因为我想按顺序排列它们,所以我可以确定它们是什么作出了得分线。我正在使用'分钟'值来对此进行排序:

@allinfogoals = sort { $a->[1] <=> $b->[1] } @allinfogoals;

这很有效,直到我遇到额外时间得分的目标。这些分钟显示为“90 + 2”或“45 + 3”。现在,我可以将它们添加到一起,但这可能会使订单不正确。在这种情况下,在半场结束前得分的进球可以存储为在下半场开始后不久得分的进球得分。

所以,我发现这些90 + x格式的分钟并将它们分成'+'。我将第一个值存储在我经常在数组中存储分钟的位置,但是我在数组末尾添加了另一个值(第12个项目),我将第二个部分(分钟加入额外的时间)放在那里。当它是常规目标时,它就是0。

如何修改上面的排序以补偿这一点并使其保持正确的顺序?

3 个答案:

答案 0 :(得分:5)

听起来你想首先对一个键进行排序,如果该键是相同的,那么你想要对第二个键进行排序。

E.g。你希望45 + 2在45到46之间排序。

您只需使用以下方法即可完成此操作:

@ls = sort { $a->[0] <=> $b->[0] || $a->[1] <=> $b->[1] } @ls

仅当第一个键相同时,才会查询第二个键。

这是一个完整的例子:

my @allinfogoals=(
                  [ 46, 0 ],
                  [ 45, 2 ],
                  [ 45, 0 ],
                  [ 33, 0 ],
                  [ 91, 0 ],
                  [ 90, 2 ],
                 );

@allinfogoals=sort { $a->[0] <=> $b->[0] || $a->[1] <=> $b->[1] } @allinfogoals;

use Data::Dump; dd \@allinfogoals;

输出是:

[[33, 0], [45, 0], [45, 2], [46, 0], [90, 2], [91, 0]]

答案 1 :(得分:2)

这是一个“蛮力”的解决方案,因为它没有太多的技巧,但是做到了。除非经过调整,否则它不适用于二维数据结构,但另一方面,我不知道您的数据结构是什么样的。

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

my @data = qw(22 45+3 45 46 90 90+3);

my @sorted = map $_->[2],               # turn back to org string
        sort {
            $a->[0] <=> $b->[0] ||      # default sort by period number
            $a->[1] <=> $b->[1]         # or by minute
        } map mysort($_), @data;        # map all minutes to 3-element array

say for @sorted;

sub mysort {
    my $time = shift;
    if ($time =~ /45\+(\d+)/) {
        return [1, 45+$1, $time];
    } elsif ($time =~ /90\+(\d+)/) {
        return [2, 90+$1, $time];
    } else {
        my $period = ($time <= 45 ? 1 : 2);
        return [$period, $time, $time]
    }
}

这使用Schwartzian transform将每分钟条目转换为三元素数组,包括句点编号,该句点内的分钟和原始字符串。该脚本的输出是:

22
45
45+3
46
90
90+3

答案 2 :(得分:0)

在这种特殊情况下,正如您所描述的那样,您也可以(如有人回答但似乎再次删除)将您的加班时间转换为十分之一并按数字顺序排列:

my @allinfogoals=qw(46 45+2 45 33 91 90+2);

@allinfogoals=map { s/[.]/+/; $_ } sort { $a <=> $b } map { s/[+]/./; $_ } @allinfogoals;

use Data::Dump; dd \@allinfogoals;

...然后转换回来。输出:

[33, 45, "45+2", 46, "90+2", 91]