Perl grep如何确定几个哈希的并集?

时间:2010-04-15 05:10:28

标签: perl grep

我不理解Programming Perl 3e中此函数的最后一行。

以下是通过返回传递给它的所有散列中出现的键列表,编写一个执行某种集合交集的函数的方法:

@common = inter( \%foo, \%bar, \%joe );
sub inter {
    my %seen;
    for my $href (@_) {
        while (my $k = each %$href) {
            $seen{$k}++;
        }
    }
    return grep { $seen{$_} == @_ } keys %seen;
}

我理解%seen是一个散列,它将每个键映射到在为函数提供的任何散列中遇到的次数。

3 个答案:

答案 0 :(得分:16)

grep将传递给它的列表(在这种情况下,在任何hashrefs中看到的每个元素);并返回仅列表中表达式为true的元素的列表(将$_变量本地设置为列表中的每个元素)。

让我们看看如何评估该表达式:

  • @_是传递给子例程的所有参数的数组 - 在我们的示例中是传入的哈希引用列表。

  • $seen{$_} == @_表达式中,该列表被强制转换为scalar context(由于==)。

  • 在标量上下文中使用时,列表会计算列表中元素的数量 - 在上面的示例调用中,为3,因为传入了3个hashref。

因此,对于%seen中的每个键(例如,在任何N个hashref中看到的每个键);表达式$seen{$_} == @_在数字上比较了在散列中看到元素的次数与散列的总数 - 当然,如果元素在所有传入的散列中,它将是相等的,因此我们想要的交叉点的成员。

因此,为了总结分析,grep将返回在每个哈希中出现的所有键的列表(也称为N次,其中N是哈希值)。例如。一个十字路口。

答案 1 :(得分:3)

grep block list 

这将依次将块应用于列表的每个元素,该元素的别名为$ _。如果块返回true,则将元素添加到返回的数组中。

在这种情况下:

grep { $seen{$_} == @_ } keys %seen

该块为$seen{$_} == @_,它将查看的哈希值与@_进行比较。 @_在标量上下文中进行计算,从而返回@_数组中的元素数。 @_表示当前函数的参数。在这种情况下( \%foo, \%bar, \%joe ),它在标量上下文中返回3。我们的列表是keys %seen,这是一个包含%seen中所有键的数组。

等同的英语陈述:

  • “给我一张所有钥匙的清单 与%seen相关联的值 该键等于数量 传递给此函数的元素“
  • “给我一张所有钥匙的清单 与%seen相关联的值 该密钥为3
  • “给我一份清单 来自%seen的所有密钥 值3,即%seen中的所有键 存在于3中的每一个中 传递给此函数的hashrefs“

答案 2 :(得分:2)

该函数的目的是找到传递给它的所有哈希中出现的元素。

grep返回的列表的最后一行keys %seen。要确定给定键是否出现在传递给函数的所有哈希值中,我们可以将%seen中的键值与inter的参数数量进行比较。

grep块中,$_设置为keys列表的每个元素,并针对某些条件进行测试。

标量上下文中的数组计算其长度。 @_是传递给子例程的参数数组。 ==运算符将其操作数放在标量上下文中,因此我们只需将$seen{$_}的值与长度@_进行比较即可。如果它们是相同的,则该键出现在所有哈希中。