将数组引用排序为哈希

syk*_*ker 9 arrays perl hash reference

在Perl中执行这些行之后:

my $data = `curl '$url'`;
my $pets = XMLin($data)->(pets);
Run Code Online (Sandbox Code Playgroud)

我有一个包含对哈希的引用的数组引用:

$VAR1 = [
      {
        'title' => 'cat',
        'count' => '210'
      },
      {
        'title' => 'dog',
        'count' => '210'
      }
]
Run Code Online (Sandbox Code Playgroud)

在Perl中,我如何首先按照计数对哈希进行排序,然后按标题对哈希进行排序.然后打印到STDOUT计数,然后打印每个换行符上的标题.

Gre*_*con 9

假设您希望按降序排列计数并且标题升序:

print map join(" ", @$_{qw/ count title /}) . "\n",
      sort { $b->{count} <=> $a->{count}
                         ||
             $a->{title} cmp $b->{title} }
      @$pets;
Run Code Online (Sandbox Code Playgroud)

这是以功能风格编写的紧凑代码.为了帮助理解它,让我们以更熟悉,命令式的方式查看等效代码.

Perl的sort运算符采用可选的SUBNAME参数,该参数允许您将比较分解出来,并为其指定一个描述其功能的名称.当我这样做时,我喜欢开始使用sub的名字,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;
Run Code Online (Sandbox Code Playgroud)

请注意,此表单中的SUBNAME后面没有逗号!

为了解决另一个评论者的问题,你可以使用or,而不是||by_count_then_title,如果你觉得它更具可读性.双方<=>cmp 具有更高的优先级比(你想象中的更紧密结合)||or,所以它是严格的风格问题.

要打印排序的数组,可能会有更熟悉的选择

foreach my $p (@sorted) {
  print "$p->{count} $p->{title}\n";
}
Run Code Online (Sandbox Code Playgroud)

$_如果您没有指定获取每个值的变量,Perl会使用,因此以下内容具有相同的含义:

for (@sorted) {
  print "$_->{count} $_->{title}\n";
}
Run Code Online (Sandbox Code Playgroud)

forforeach关键字是同义词,但我发现,上面的用途,,foreach如果我要去命名变量或for否则,读最自然的.

使用map,近亲foreach,但没有太大的不同:

map print("$_->{count} $_->{title}\n"), @sorted;
Run Code Online (Sandbox Code Playgroud)

你也可以print通过以下方式宣传map:

print map "$_->{count} $_->{title}\n",
      @sorted;
Run Code Online (Sandbox Code Playgroud)

最后,为了避免重复$_->{...},散列片 @$_{"count", "title"}给出了与循环当前记录中的count和title相关的值.拥有这些值后,我们需要将它们与一个空格连接起来,并为结果添加换行符,所以

print map join(" ", @$_{qw/ count title /}) . "\n",
      @sorted;
Run Code Online (Sandbox Code Playgroud)

请记住,这qw//是编写字符串列表的简写.如此示例所示,map从前向后(或从我缩进的方式从下到上)读取表达式:首先对记录进行排序,然后对其进行格式化,然后打印它们.

您可以消除临时@sorted但调用命名比较:

print map join(" ", @$_{qw/ count title /}) . "\n",
      sort by_count_then_title
      @$pets;
Run Code Online (Sandbox Code Playgroud)

如果应用程序join对您的口味过于冗长,那么

print map "@$_{qw/ count title /}\n",
      sort by_count_then_title
      @$pets;
Run Code Online (Sandbox Code Playgroud)