按字典顺序排序

发布于 2024-07-24 14:53:40 字数 667 浏览 3 评论 0原文

我看到以下代码的结果,但我不明白 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);

I see the results from the following code, but I don't understand exactly how the or knows what to do in the following sort example:

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);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

鼻尖触碰 2024-07-31 14:53:40

sortsub({}sort 之后的内容)定义了两层排序:首先按名称排序,然后按分支数排序。 or 实现了两个标准之间的交叉。 如果您以不同的方式设置代码格式,则更容易查看:

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

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

在进行多层排序时,通常使用“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;

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

The sortsub (the stuff in {} after the sort) defines a two-tier sort: first by name, then by number of legs. The or implements the cross-over between the two criteria. It's easier to see if you format the code differently:

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

The cmp and <=> operators return one of three values (-1, 0, or 1) depending on whether the left argument is less than, equal to, or greater than the right argument. (cmp does a string comparison, <=> does a numeric one.) In Perl, 0 is false while -1 and 1 are true. If the cmp returns a true value, the or returns that value immediately, and sort reorders the elements appropriately. If the cmp returns false, the <=> is evaluated and its result is returned instead.

When doing multi-layer sorts, it's common to use a "map-sort-map" technique (a.k.a. Schwartzian Transform):

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

It's not as clear but because it usually has better performance it's a common idiom. This is especially important when the operands to the comparison are functions -- this technique prevents an unnecessary (and possibly expensive) recalculation for every comparison. For example, if you're sorting strings by length you only need to compute the length of each string once.

怀里藏娇 2024-07-31 14:53:40

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

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

or is a short-circuit evaluator, so it will return the value of the left-hand side if it's true (which is any non-zero value), and otherwise will evaluate the right-hand side.

So in this case, if the animals' names compare as equal, (0 - false), the number of legs will be counted for sorting purposes.

岁月流歌 2024-07-31 14:53:40

我可以建议 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;

May I suggest Sort::Key as an alternative for the present code altogether?

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文