在perl中对间隔数组进行排序?

Shi*_*ari 4 perl

我在perl中有一个数组,有一些间隔,如:

@array = qw(1-5 7-9 10-15 20-58 123-192 234-256)

我试图使用排序来订购它,但这是我获得的:

1-5,10-15,123-192,20-58,234-256,7-9

它按第一个数字的第一个字符排序......为了获得下一个数组,如何按整个第一个数字排序?

1-5,7-9,10-15,20-58,123-192,234-256

非常感谢你!

PS

我没有这个代码,我正在尝试这个命令

my @sorted = sort @array;
Run Code Online (Sandbox Code Playgroud)

Сух*_*й27 5

您需要为每个元素提取第一个数字,并使用<=>运算符进行数值比较,

my @array = qw(1-5 7-9 10-15 20-58 123-192 234-256);
my @sorted = sort {
  my ($aa,$bb) = map /^([0-9]+)/, $a,$b; 

  $aa <=> $bb;
} @array;
Run Code Online (Sandbox Code Playgroud)


TLP*_*TLP 5

你想要做的是按数字排序.为此,您需要通过提供自己的方法来覆盖默认排序方法.这段代码:

my @sorted = sort @array;
Run Code Online (Sandbox Code Playgroud)

真的意思是:

my @sorted = sort { $a cmp $b } @array;
Run Code Online (Sandbox Code Playgroud)

cmp字典比较运算符在哪里(按字母顺序排序,或多或少).你想使用<=>通常被称为"宇宙飞船运营商"的人.

my @sorted = sort { $a <=> $b } @array;
Run Code Online (Sandbox Code Playgroud)

但是这个运算符只能用于数字,而字符串7-9就不是真正的数字(尽管在这种情况下它会起作用,尽管会发出警告Argument "7-9" isn't numeric in sort).

为了克服这个警告和可能的错误,我们需要从我们想要排序的字符串中提取数字.我们用正则表达式匹配来做到这一点:/\d+/g.这将匹配并返回字符串中的所有连续数字.

my @sorted = sort {
                     my ($a1, $a2) = $a =~ /\d+/g;
                     my ($b1, $b2) = $b =~ /\d+/g;
                     $a1 <=> $b1 || $a2 <=> $b2;
} @array;
Run Code Online (Sandbox Code Playgroud)

我们捕获并使用低和高范围,最后我们执行两个检查.这意味着,在该情况下$a1$b1是相等的,<=>返回0,和所述||操作者执行替代比较,$a2 <=> $b2.

在某些情况下,此操作很昂贵,需要时间,并且使用大型数据集会导致排序变得非常慢.在这种情况下,我们可以使用所谓的Schwartzian变换来缓存数据.在这个方法中,我们只是存储正则表达式匹配的值,并在排序时使用存储的值.为此,我们使用匿名数组ref [ ... ].最后,我们恢复原始值并丢弃缓存:

my @sorted = map  { $_->[0] }                # restore original
             sort { $a->[1] <=> $b->[1] }    # sort compares stored nums
             map  { [ $_, /\d+/g ] }         # store original, and nums
             @array;
Run Code Online (Sandbox Code Playgroud)

如果您想要多个排序级别,只需添加$a->[2] <=> $b->[2]等等.