代码之家  ›  专栏  ›  技术社区  ›  wes

为什么Perl的移位会抱怨“要移位的arg 1类型必须是数组(而不是grep迭代器)。”

  •  10
  • wes  · 技术社区  · 15 年前

    我有一个数据结构,它是一个散列,包含一个散列数组。我想在那里,并拿出第一个散列值,匹配我正在寻找的值。我试过这个:

       my $result = shift grep {$_->{name} eq 'foo'} @{$hash_ref->{list}};
    

    但这给了我一个错误: Type of arg 1 to shift must be array (not grep iterator). 我重新读过 perldoc 对于 grep 我觉得我所做的是有道理的。 格雷普 返回一个列表,对吗?是不是上下文不对?

    现在我将使用一个临时变量,但我想弄清楚为什么这不起作用。

    3 回复  |  直到 13 年前
        1
  •  18
  •   Quentin    13 年前

    A list isn't an array .

    my ($result) = grep {$_->{name} eq 'foo'} @{$hash_ref->{list}};
    

    但还是应该做这项工作。在列表上下文中获取grep返回的值,但不要分配除第一个值以外的任何值。

        2
  •  17
  •   Leon Timmermans    15 年前

    我认为更好的方法是这样写:

    use List::Util qw/first/;
    
    my $result = first { $_->{name} eq 'foo' } @{ $hash_ref->{list} };
    

    这样不仅可以更清楚地知道您要做什么,还可以更快,因为一旦找到匹配的元素,它将停止重新映射数组。

        3
  •  2
  •   Community CDub    8 年前

    另一种方法是:

    my $result = (grep {$_->{name} eq 'foo'} @{$hash_ref->{list}})[0];
    

    注意第一个参数周围的卷曲 grep 在这种情况下是多余的,因此您可以使用

    my $result = (grep $_->{name} eq 'foo', @{$hash_ref->{list}})[0];
    

    “List value constructors” in perldata 订阅列表的文档:

    列表值也可以像普通数组一样下标。为了避免歧义,你必须把这个列表放在括号里。例如:

    # Stat returns list value.
    $time = (stat($file))[8];
    
    # SYNTAX ERROR HERE.
    $time = stat($file)[8];  # OOPS, FORGOT PARENTHESES
    
    # Find a hex digit.
    $hexdigit = ('a','b','c','d','e','f')[$digit-10];
    
    # A "reverse comma operator".
    return (pop(@foo),pop(@foo))[0];
    

    我记得,我们在 Randal Schwartz 开玩笑的建议,而且 Chip Salzenberg “那时候谁是打补丁的机器”那天晚上就实现了。

    更新: 一点点的搜索显示出我的想法是 $coderef->(@args) . 提交消息甚至记录了对话!