【问题标题】:simple perl to iterate over hash returned from subroutine in one line?简单的 perl 在一行中迭代从子例程返回的哈希?
【发布时间】:2015-12-28 21:26:48
【问题描述】:

假设我有一个返回哈希结果的子程序。我想从我的父目录中的子例程中迭代键/值对,并且不想先将结果保存到变量中。

这看起来很简单,但我完全不知道该怎么做。如果该方法返回一个哈希,我不知道告诉循环期望从该方法返回一个哈希所需的语法。如果该方法返回一个 hashref 我可以做

while( my($key,$value) = each ( %{ generate_hash() } )

但这会在每次循环完成时重新运行 generate_hash() 方法,重新生成相同的哈希,并重新处理哈希的第一个元素(或者至少在 5.10 中这样做。5.14 允许每个都采用一个标量,这可能会解决问题,不确定,但遗憾的是我仅限于 5.10。

谁能解释一下我在这里遗漏了什么明显的语法?

【问题讨论】:

  • "并且不想先将结果保存到变量中。"这确实是降低代码可读性的一个糟糕的理由。
  • 我不确定您是否可以在指定的约束范围内执行此操作。要迭代哈希,您确实需要keyseach,并且在这两种情况下,您都需要“访问”两次哈希。 (我想你可以在紧要关头一次迭代一个元素,但是你仍然需要使用 var 再次将它们粘在一起)

标签: perl hash


【解决方案1】:
use List::Util 1.29 'pairs';

for my $kv ( pairs %{ genHash() } ) {
    my ($key, $value) = @$kv;
    ...
}

【讨论】:

    【解决方案2】:

    免责声明评论者是正确的并且这是一个坏主意,您可以

    1. 将赋值放在%{...} 演员表中。仍然不那么可读,不会使代码更简洁,除非您可以将 my 声明与之前的声明相结合:

      my $foo;
      while (my ($k,$v) = each %{$foo //= generate_hash}) { ... }
      
    2. 确保generate_hash 每次调用时都返回对相同哈希的引用。这样,与哈希关联的迭代器将被重用并为您提供一个新密钥。当然,最简单的方法是使用变量:

      my $cached_generated_hash;
      sub generate_hash {
          return $cached_generated_hash //= do {
             ...
             { abc => 123, def => 456 }
          };
      }
      

    【讨论】:

      【解决方案3】:

      同意@mob 和评论者的观点,以下内容仅供娱乐。似乎没有成效,但如果有人可以远程提取一些东西,比如“荒谬的简单语法”来做到这一点,我会很感兴趣:-)

      哦,是的,注意 genHash() 的单一调用。

      $ ./foo.pl
      Hello from genHash()
      a=beta
      a=2
      a=alpha
      a=1
      a=gamma
      a=3
      
      $ cat ./foo.pl
      #!/usr/bin/perl
      
      use strict;
      
      sub genHash() {
         print "Hello from genHash()\n";
         return { alpha => 1, beta => 2, gamma => 3 };
      }
      
      # There comes a point when you have to ask
      # why you are even trying to swim upstream :-)
      # ----- edit as per comments to remove unnecessary reference.
      # original: foreach my $a ( %${ \( genHash() ) } ) {
      # ------------------------------
      foreach my $x ( %{ genHash() } ) {
         print "x=", $x, "\n";
      }
      
      $
      

      【讨论】:

      • 无需引用并立即取消引用,foreach my $foo (%{genHash()}){...} 给出相同的结果。请注意,永远不要将 $a$b 词汇化,因为它们是为 sort 保留的。
      • 酷 - 谢谢,@ThisSuitIsBlackNot - 进行了相应的编辑。我经常使用 %$someref 并且没想过只用 %{genHash()}
      猜你喜欢
      • 2014-07-02
      • 1970-01-01
      • 2013-11-20
      • 2023-04-07
      • 2017-09-04
      • 2020-12-08
      • 2014-10-27
      • 2013-04-30
      • 2016-03-28
      相关资源
      最近更新 更多