【问题标题】:"Statement modifier" iteration over a hash?散列上的“语句修饰符”迭代?
【发布时间】:2018-09-09 08:22:02
【问题描述】:

我发现自己想在 Perl (v5) 中对哈希使用语句修饰符形式的迭代:

my %h = (...);
do_something($_[0], $_[1]) for each %h;  ### $_[0] => key, $_[1] => val

或者:

my %h = (...);
my @ary = %h;
do_something($_[0], $_[1]) for splice(@ary, 0, 2);

当然,这两种形式都不存在。只是好奇是否有任何工作支持spliceeachfor 的语句修饰符形式一起使用?在 Perl 6 或通过 backport v5 中?

【问题讨论】:

  • each 甚至不是循环。
  • @melpomene 好点子,我已经更新了帖子以将eachsplice 放在同一位置
  • for each %h 已经做了其他事情:each 返回一个包含两个元素的列表(键、值),for 对其进行迭代。
  • “语句修饰符”是指修改$_[0]$_[1]的值的do_something(...)函数吗?
  • @mob:“语句修饰符”是指此处描述的 Perl 语法:perldoc.perl.org/perlsyn.html#Statement-Modifiers

标签: perl loops foreach syntax iterator


【解决方案1】:

List::UtilList::MoreUtils 中有一些很棒的函数可以帮助解决这种情况。特别是看pairs

use List::Util qw{pairs};

do_something($_->[0], $_->[1]) foreach pairs %h;

或者,如果您可以在 void 上下文中忍受地图:

use List::Util qw{pairmap};

pairmap { do_something($a, $b) } %h;

【讨论】:

  • 啊,List::Util,我应该知道 :) 我还想出了以下方法:do_something($_->[0], $_->[1]) for map { CORE::state @bob; push @bob, $_; @bob % 2 ? () : do {my @tmp = @bob; @bob = (); \@tmp} } %h(也许 List::Utils::pairs 在场景?)我只是想看看其他人想出了什么,所以我改天再打开它。否则你的答案似乎可以接受。
  • @textral,do {my @tmp = @bob; @bob = (); \@tmp} 是写[splice(@bob)] 的漫长道路。如果提供了奇数个参数,你的解决方案就会失败(即很糟糕)。
【解决方案2】:

最干净的解决方案如下:

do_something($_, $h{$_}) for keys %h;

如果你想节省内存,你可以像往常一样使用each

{ my ($k, $v);  do_something($k, $v) while ($k, $v) = each(%h); }

当然,不使用语句修饰符会更简洁。

while (my ($k, $v) = each(%h)) { do_something($k, $v); }

最后,如果您实际上不处理哈希,可以使用来自List::Utilpairs

use List::Util qw( pairs );

do_something(@$_) for pairs %h;

最后一种方法非常浪费,因为它低效地创建了大量数组。

【讨论】:

  • 哦对了:我以前用过你的第一个表格……不知道为什么我这次没有想到。尽管这可能是最好的方法,但我认为我必须接受@mwp 的回答,因为我最初的问题(即使我措辞不佳)更多的是关于如何使用循环语句修饰符一次从列表中消耗多个元素.我知道从技术上讲 Perl 不允许(目前?),但至少 List::Util::pairs 给出了确切的“印象”(@mwp 首先发布了关于 List::Util::pairs 的信息)。
  • 请注意,您仍然可以像往常一样使用each
  • 我不知道你为什么说使用pairs 是mwp 的解决方案;我也提出来了,甚至还提供了更简单的使用方式。
  • 这很危险,应该避免
  • local 在那里没有做任何事情,因为没有卷曲来限制它
【解决方案3】:

你可以缩短

{my ($k, $v);  do_something($k, $v) while ($k, $v) = each(%h); }

do_something($a, $b) while ($a, $b) = each %h;

因为 $a 和 $b 已经被声明为排序。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-27
    • 1970-01-01
    • 2018-03-30
    • 2022-12-05
    • 2012-05-01
    • 1970-01-01
    • 2022-01-23
    相关资源
    最近更新 更多