如果我有一个具有以下格式的字符串数组:
[1900] ABC 15
如何使用perl sort
对数组进行排序,以便按第一个数字排序,然后按第二个排序?
来自perldoc sort的示例似乎是相关的:
my @new = sort {
($b =~ /=(\d+)/)[0] <=> ($a =~ /=(\d+)/)[0]
||
fc($a) cmp fc($b)
} @old;
答案 0 :(得分:4)
从文档中提取的示例显示了这样的想法:按一个标准进行比较,如果它们被cmp
或<=>
equality operators找到相等,然后返回0
,转到下一个标准。
所以在这种情况下,比较字符串中的第一个数字,然后是第二个数字。
use warnings;
use strict;
use feature 'say';
my @old = ('[1900] ABC 15', '[1900] ABC 5', '[1800] ABC 20');
my @new = sort {
my ($a1, $a2) = $a =~ /([0-9]+)/g;
my ($b1, $b2) = $b =~ /([0-9]+)/g;
$a1 <=> $b1 or $a2 <=> $b2;
} @old;
say for @new;
打印
[1800] ABC 20 [1900] ABC 5 [1900] ABC 15
如果排序需要按降序排列,请在比较中交换a
和b
。
这可以通过预先计算整个列表的正则表达式来更有效地完成,这样每次比较元素时都不会重新完成它们。文档中示例的延续显示了这一点,最后一个版本是Schwartzian transform。
但请记住,这种优化只适用于较大的数据集,而且对于简单的计算,它们的开销也很重要。
上述基本sort
通常就足够了。
注意 [0-9]
与\d
匹配,但其他字符也是如此(我告诉其他360个字符),它具有Unicode识别功能。对于/a
字符集修饰符,情况并非如此,自5.14起可用。但这比限制\d
更有效。在perlre中搜索/a
。
因此,我使用0-9
来提高精度和效率,并且不限制\s
,\w
和POSIX字符类。
答案 1 :(得分:-1)
我前段时间写了一个函数做这种排序。 它使用字符串中的所有数字进行数字排序。 抱歉,我不关心表演。希望它有所帮助。
sub num_sort($$) {
my ($a,$b)=@_;
my @sa=reverse grep /./s, split /(\d+)/,$a;
my @sb=reverse grep /./s, split /(\d+)/,$b;
for (;; ) {
last if !@sa || !@sb;
my $ea=pop @sa;
my $eb=pop @sb;
my $rc= ($ea <=> $eb) || ($ea cmp $eb);
if ($rc) {
return $rc;
}
}
return @sa <=> @sb;
}