perl - 对哈希值的数组引用进行排序

标签 perl arrays reference hash

在 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";
}

forforeach关键字是同义词,但我发现上面的用法,foreach如果我要命名一个变量或 for否则,请以最自然的方式阅读。

使用mapforeach 的近亲,其实并没有太大不同:

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/

相关文章:

javascript - 使用多个键过滤数组

c++ - 在 C++ 中将对象序列化为字节数组

c# - 是否可以获取 C# 对象地址的字符串表示形式?

javascript - 动态数组名称javascript

c++ - 是否有解决 undefined reference /未解析符号问题的通用指南?

.net - 如何使用程序集绑定(bind)重定向来忽略修订和内部版本号

regex - 如何使用 m!在 Perl 正则表达式中

perl - (4 + sub)等于(sub + 4)吗?

while 循环中的 bool (标量)上下文中的 Perl 列表

perl - 如何使用变量名引用哈希?