在perl中排序列表时出现问题

时间:2018-04-22 10:52:19

标签: list perl sorting comparison

我有一个表示时间值的字符串列表,即1us,100ps,10s,7fs(微秒,皮秒,秒,飞秒等)。 我需要按升序对列表进行排序。为此,我编写了一个比较例程,当给出两个字符串时,将每个字符串转换为相应的数值并进行比较。但是,列表没有正确排序。经过多次调试后,我感到很茫然。这是我的代码:

#!/usr/bin/perl
use warnings;
use strict;
   my %scales = ('fs'=>1e-15,'ps'=>1e-12,'ns'=>1e-9,'us'=>1e-6,'ms'=>1e-3,'s'=>1);
   my @times = ('1s','7ns','100ps','500ms','9us');
   my @stimes = sort bytime @times;
   sub bytime {

      my $op1 = $a;
      my $op2 = $b;
      $op1 =~ /\b(\d+)([munpf]*s)\b/;
      my $v1 = $1 * $scales{$2};
      $op2 =~ /\b(\d+)([munpf]*s)\b/;
      my $v2 = $1 * $scales{$2};
      return $v1 > $v2;
}

print "@times"."\n"."@stimes"."\n";

我得到的结果是:

1s 7ns 100ps 500ms 9us

100ps 7ns 500ms 1s 9us

这显然是错误的,即使进行了一些排序。 发生了什么事?

1 个答案:

答案 0 :(得分:7)

您的错误就行了

return $v1 > $v2;

如果$v1大于$v2,则返回1(true),在所有其他情况下,0(false)将返回

您希望改为使用数值比较运算符<=>

return $v1 <=> $v2;

将返回1,0或-1,具体取决于比较结果,并允许排序正常工作。 (如果您处理字符串而不是数字,则运算符为cmp。)

完整的工作代码:

#!/usr/bin/perl
use warnings;
use strict;

my %scales = ('fs'=>1e-15,'ps'=>1e-12,'ns'=>1e-9,'us'=>1e-6,'ms'=>1e-3,'s'=>1);
my @times = ('1s','7ns','100ps','500ms','9us');
my @stimes = sort bytime @times;

sub bytime {
    my $op1 = $a;
    my $op2 = $b;
    $op1 =~ /\b(\d+)([munpf]*s)\b/;
    my $v1 = $1 * $scales{$2};
    $op2 =~ /\b(\d+)([munpf]*s)\b/;
    my $v2 = $1 * $scales{$2};
    return $v1 <=> $v2;
}

print "@times"."\n"."@stimes"."\n";

输出:

1s 7ns 100ps 500ms 9us
100ps 7ns 9us 500ms 1s