如何按字母数字字符串中的数字排序?

时间:2017-08-28 22:21:55

标签: regex perl sorting

如果我有一个具有以下格式的字符串数组:

[1900] ABC 15

如何使用perl sort对数组进行排序,以便按第一个数字排序,然后按第二个排序?

来自perldoc sort的示例似乎是相关的:

my @new = sort {
    ($b =~ /=(\d+)/)[0] <=> ($a =~ /=(\d+)/)[0]
                        ||
                fc($a)  cmp  fc($b)
} @old;

2 个答案:

答案 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

如果排序需要按降序排列,请在比较中交换ab

这可以通过预先计算整个列表的正则表达式来更有效地完成,这样每次比较元素时都不会重新完成它们。文档中示例的延续显示了这一点,最后一个版本是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;
}