在 Perl 中执行这些行后:
my $data = `curl '$url'`;
my $pets = XMLin($data)->(pets);
我有一个数组引用,其中包含对哈希的引用:
$VAR1 = [
{
'title' => 'cat',
'count' => '210'
},
{
'title' => 'dog',
'count' => '210'
}
]
在 Perl 中,如何首先按计数排序哈希,然后按标题排序。然后将计数打印到 STDOUT,后跟每个换行符上的标题。
最佳答案
假设您希望计数按降序排列,标题按升序排列:
print map join(" ", @$_{qw/ count title /}) . "\n",
sort { $b->{count} <=> $a->{count}
||
$a->{title} cmp $b->{title} }
@$pets;
这是以函数式风格编写的紧凑代码。为了帮助理解它,让我们以更熟悉的命令式风格查看等效代码。
Perl 的 sort
运算符采用可选的 SUBNAME 参数,该参数允许您分解比较并为其指定一个描述其用途的名称。当我这样做时,我喜欢以 by_
开头子名称。制作sort by_...
准备得更自然。
首先,您可能已经编写了
sub by_count_then_title {
$b->{count} <=> $a->{count}
||
$a->{title} cmp $b->{title}
}
my @sorted = sort by_count_then_title @$pets;
请注意,在此形式中 SUBNAME 后面没有逗号!
要解决其他评论者的问题,您可以使用 or
而不是||
在by_count_then_title
如果您发现它更具可读性。两者<=>
和cmp
have higher precedence (您可能认为绑定(bind)更紧密)比 ||
和or
,所以这完全是一个风格问题。
要打印排序后的数组,更熟悉的选择可能是
foreach my $p (@sorted) {
print "$p->{count} $p->{title}\n";
}
Perl 使用$_
如果不指定获取每个值的变量,则以下内容具有相同的含义:
for (@sorted) {
print "$_->{count} $_->{title}\n";
}
for
和foreach
关键字是同义词,但我发现上面的用法,即,foreach
如果我要命名一个变量或 for
否则,请以最自然的方式阅读。
使用map
, foreach
的近亲,其实并没有太大不同:
map print("$_->{count} $_->{title}\n"), @sorted;
您还可以推广print
通过map
:
print map "$_->{count} $_->{title}\n",
@sorted;
最后,为了避免重复$_->{...}
,hash slice @$_{"count", "title"}
为我们提供与循环当前记录中的计数和标题相关的值。有了这些值,我们需要 join他们用一个空格并在结果中附加一个换行符,所以
print map join(" ", @$_{qw/ count title /}) . "\n",
@sorted;
请记住 qw//
是编写字符串列表的简写。如本示例所示,请阅读 map
表达式从后到前(或按照我缩进的方式从下到上):首先对记录进行排序,然后格式化它们,然后打印它们。
您可以消除临时 @sorted
但调用命名比较:
print map join(" ", @$_{qw/ count title /}) . "\n",
sort by_count_then_title
@$pets;
如果申请join
对于您的口味来说太冗长了,那么
print map "@$_{qw/ count title /}\n",
sort by_count_then_title
@$pets;
关于perl - 对哈希值的数组引用进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3137332/