【问题标题】:sort with lexicographic order按字典顺序排序
【发布时间】:2009-06-17 20:29:10
【问题描述】:

我看到以下代码的结果,但我不明白or 是如何知道在以下sort 示例中要做什么:

use Data::Dumper;

$animals{'man'}{'name'} = 'paul';
$animals{'man'}{'legs'} = 2;
$animals{'cheeta'}{'name'} = 'mike';
$animals{'cheeta'}{'legs'} = 3;
$animals{'zebra'}{'name'} = 'steve';
$animals{'zebra'}{'legs'} = 4;
$animals{'cat'}{'name'} = '';
$animals{'cat'}{'legs'} = 3;
$animals{'dog'}{'name'} = '';
$animals{'dog'}{'legs'} = 4;
$animals{'rat'}{'name'} = '';
$animals{'rat'}{'legs'} = 5;

@animals = sort {
      $animals{$a}{'name'} cmp $animals{$b}{'name'}
   or $animals{$a}{'legs'} <=> $animals{$b}{'legs'}
} keys %animals;

print Dumper(\@animals);

【问题讨论】:

    标签: perl sorting cmp lexicographic


    【解决方案1】:

    sortsub({}sort 之后的内容)定义了两层排序:首先按名称,然后按腿数。 or 实现了两个标准之间的交叉。更容易看出您是否以不同的方式格式化代码:

    @animals = sort {
        $animals{$a}{'name'} cmp $animals{$b}{'name'} or
        $animals{$a}{'legs'} <=> $animals{$b}{'legs'}
    } keys %animals;
    

    cmp&lt;=&gt; 运算符返回三个值之一(-1、0 或 1),具体取决于左侧参数是小于、等于还是大于右侧参数。 (cmp 进行字符串比较,&lt;=&gt; 进行数字比较。)在 Perl 中,0 为假,而 -1 和 1 为真。如果cmp 返回一个真值,or 立即返回该值,sort 适当地重新排序元素。如果 cmp 返回 false,则评估 &lt;=&gt; 并返回其结果。

    在进行多层排序时,通常使用“map-sort-map”技术(又名Schwartzian Transform):

    @animals =
      map  { $_->[0] }
      sort {
        $a->[1] cmp $b->[1] ||
        $a->[2] <=> $b->[2]
      }
      map { [$_, $animal{$_}{name}, $animal{$_}{legs}] }
      keys %animal;
    

    这不是很清楚,但因为它通常具有更好的性能,所以它是一个常见的习语。当比较的操作数是函数时,这一点尤其重要——这种技术可以防止对每次比较进行不必要的(并且可能是昂贵的)重新计算。例如,如果您按长度对字符串进行排序,则只需计算每个字符串的长度一次。

    【讨论】:

      【解决方案2】:

      or 是一个短路求值器,因此如果为真(即任何非零值),它将返回左侧的值,否则将评估右侧的值。

      所以在这种情况下,如果动物的名字比较相等,(0 - false),将计算腿的数量以进行排序。

      【讨论】:

        【解决方案3】:

        我可以建议Sort::Key 完全替代当前代码吗?

        use Sort::Key::Multi qw(sikeysort);  # sort keyed on (string, integer)
        @animals = sikeysort { $animals{$_}{name}, $animals{$_}{legs} } keys %animals;
        
        # alternately,
        use Sort::Key::Maker sort_by_name_then_legs =>
            sub { $animals{$_}{name}, $animals{$_}{legs} }, qw(string integer);
        @animals = sort_by_name_then_legs keys %animals;
        

        【讨论】:

          猜你喜欢
          • 2010-10-24
          • 1970-01-01
          • 2019-12-24
          • 2020-08-02
          • 2015-06-23
          • 1970-01-01
          • 2019-01-07
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多