将数组引用排序为哈希

时间:2010-06-29 01:49:58

标签: 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计数,然后打印每个换行符上的标题。

1 个答案:

答案 0 :(得分:9)

假设您希望按降序计数和标题升序:

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(您可能认为绑定比||or更紧密),所以这完全是风格问题。< / p>

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

foreach my $p (@sorted) {
  print "$p->{count} $p->{title}\n";
}

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

for (@sorted) {
  print "$_->{count} $_->{title}\n";
}

forforeach关键字是同义词,但如果我要命名变量,我会发现上面的用法 ie foreach或者for否则,最自然地阅读。

使用mapforeach的亲密关系,并没有太大的不同:

map print("$_->{count} $_->{title}\n"), @sorted;

您还可以通过print

宣传map
print map "$_->{count} $_->{title}\n",
      @sorted;

最后,为了避免重复$_->{...}hash slice @$_{"count", "title"}为我们提供了与循环当前记录中的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;