【问题标题】:How can I print the contents of a hash in Perl?如何在 Perl 中打印散列的内容?
【发布时间】:2010-11-12 19:57:37
【问题描述】:

我一直将我的哈希打印为# of buckets / # 分配。 如何打印哈希的内容?

最好不使用while 循环(例如,最好使用one-liner)。

【问题讨论】:

    标签: perl hash printing


    【解决方案1】:

    Data::Dumper 是你的朋友。

    use Data::Dumper;
    my %hash = ('abc' => 123, 'def' => [4,5,6]);
    print Dumper(\%hash);
    

    会输出

    $VAR1 = {
              'def' => [
                         4,
                         5,
                         6
                       ],
              'abc' => 123
            };
    

    【讨论】:

    • 原始发帖人可能还想研究各种 Data::Dumper 选项,尤其是打开“排序键”可能非常有用
    • @JonathanDay 我错过了那个细节,这很有帮助!谢谢!
    • % 前面加斜线是什么意思?
    • @shampoo 斜线运算符创建一个引用,有点像 C 和 C++ 中的 & 运算符。在这种情况下它很重要的原因是,在 Perl 中,如果您调用一个以哈希值作为参数的函数,该哈希值将被列出并扩展为多个参数 - 所以 %hsh=("a" => 1, "b" => 2); foo(%hsh); 将等效于 foo("a", 1, "b", 2)。如果您希望函数对哈希本身进行操作,则需要传递对哈希的引用:foo(\%hsh); 请参阅perldoc.perl.org/perlsub.html#Pass-by-Reference
    【解决方案2】:

    简单:

    print "$_ $h{$_}\n" for (keys %h);
    

    优雅,但实际上慢了 30% (!):

    while (my ($k,$v)=each %h){print "$k $v\n"}
    

    【讨论】:

    • Sleazy: print "@_\n" while @_ = each %h
    • 我想你的意思是print "$_ $h{$_}\n" for (keys %h);$k 在那个例子中不存在。
    • 另外,在声称效率之前进行基准测试(或者至少限定您正在谈论的效率类型)。 for 循环比 while 更快,最多至少 10,000 个键:gist.github.com/151792
    • 当然你是对的:$k。但它在 Perl 6 中更有效! :) 是的,你也是对的。我从来没有想过要真正优化或分析我的 Perl,但我很高兴学习到这一点。当然,每个 应该 更有效(因为没有额外的哈希查找键)。但它慢了约 30%!
    • 嗨,乔纳森·格雷尔。对不起,还是不明白。你是说每个都慢 30% 基于什么?每次,对于每种情况,都有 30% 的差距吗?
    【解决方案3】:

    这里如何不使用Data::Dumper 进行打印

    print "@{[%hash]}";
    

    【讨论】:

      【解决方案4】:

      出于调试目的,我会经常使用YAML

      use strict;
      use warnings;
      
      use YAML;
      
      my %variable = ('abc' => 123, 'def' => [4,5,6]);
      
      print "# %variable\n", Dump \%variable;
      

      结果:

      # %variable
      ---
      abc: 123
      def:
        - 4
        - 5
        - 6
      

      其他时候我会使用Data::Dump。与Data::Dumper 相比,您不需要设置尽可能多的变量以使其以良好的格式输出。

      use Data::Dump = 'dump';
      
      print dump(\%variable), "\n";
      
      { abc => 123, def => [4, 5, 6] }
      

      最近我一直在使用Data::Printer 进行调试。

      use Data::Printer;
      p %variable;
      
      {
          abc   123,
          def   [
              [0] 4,
              [1] 5,
              [2] 6
          ]
      }
      

      (结果在终端上可以更加丰富多彩)

      与我在此处展示的其他示例不同,此示例明确设计为仅用于显示目的。如果您转储绑定变量或对象的结构,则更容易显示出来。

      use strict;
      use warnings;
      
      use MTie::Hash;
      use Data::Printer;
      
      my $h = tie my %h, "Tie::StdHash";
      @h{'a'..'d'}='A'..'D';
      p %h;
      print "\n";
      p $h;
      
      {
          a   "A",
          b   "B",
          c   "C",
          d   "D"
      } (tied to Tie::StdHash)
      
      Tie::StdHash  {
          public methods (9) : CLEAR, DELETE, EXISTS, FETCH, FIRSTKEY, NEXTKEY, SCALAR, STORE, TIEHASH
          private methods (0)
          internals: {
              a   "A",
              b   "B",
              c   "C",
              d   "D"
          }
      }
      

      【讨论】:

      • 颜色很“整洁”,但要么我做错了,要么使用“use Data::Printer; p %var;”不打印哈希中的箭头,对于像我这样的新手有帮助
      • @Sosi 如果您查看答案中的输出,您会发现它没有像您期望的那样输出=>。相反,它总是打印键、几个空格,然后是值。这有助于人工扫描输出。
      【解决方案5】:

      答案取决于哈希中的内容。如果你有一个简单的哈希一个简单的

      print map { "$_ $h{$_}\n" } keys %h;
      

      print "$_ $h{$_}\n" for keys %h;
      

      可以,但是如果您有一个填充了引用的散列,那么您将有一些东西可以遍历这些引用并产生合理的输出。引用的这种遍历通常称为序列化。有许多实现不同样式的模块,其中一些比较流行的是:

      由于Data::Dumper 是核心Perl 库的一部分,它可能是最流行的;然而,其他一些模块提供了非常好的东西。

      【讨论】:

        【解决方案6】:

        我最喜欢的:Smart::Comments

        use Smart::Comments;
        # ...
        
        ### %hash
        

        就是这样。

        【讨论】:

        • 抱歉,我对那些劫持 cmets 以获得实际功能的东西投了反对票。维护程序员可能会花一整天的时间来弄清楚为什么这样的代码会打印出意想不到的东西。
        • @MikeKulls,np。这是一个源过滤器,所以我理解。此外,编写了脚本来检查我投入生产准备的每个模块,它没有useSmart::Comments,我也从这个角度看待它。但是对于柜台来说,Smart::Comments 作为一个 scoped 模块表现得非常好,在任何不使用 SC的模块中都不应该有输出行为。因此,问题将被隔离到具有 use 语句的那些范围内。如果您说维护程序员没有责任阅读包含模块的文档,我不能同意。不过,感谢您的评论
        • 我并不是说他们没有责任,但这不太可能是他们首先要寻找的东西。在我不知道为什么上面的代码打印出来之前,我从来没有见过智能评论模块。我可以花几天的时间跳过评论,甚至不处理它,因为 cmets 应该什么都不做。让他们做某事是非常糟糕的。只要它们不改变程序的行为,它们就可以用于生成文档等。
        【解决方案7】:

        循环:

        foreach(keys %my_hash) { print "$_ / $my_hash{$_}\n"; }
        

        功能性

        map {print "$_ / $my_hash{$_}\n"; } keys %my_hash;
        

        但为了纯粹的优雅,我不得不选择 wrang-wrang's。对于我自己的代码,我会选择我的 foreach。或者 tetro 的 Dumper 使用。

        【讨论】:

        • 您对foreachmap 的使用在功能上没有区别。 map 应该用于列表转换,而不是在 void 上下文中模拟 for 循环
        • 看看每个的“字节码”结果会很有趣......我想知道 map 的效率更高还是更低。
        【解决方案8】:

        根据我的经验,最简单的方法就是使用Dumpvalue

        use Dumpvalue;
        ...
        my %hash = { key => "value", foo => "bar" };
        my $dumper = new DumpValue();
        $dumper->dumpValue(\%hash);
        

        像一个魅力一样工作,您不必担心格式化哈希,因为它像 Perl 调试器一样输出它(非常适合调试)。另外,Dumpvalue 包含在 Perl 模块的库存集合中,因此如果您使用某种严格的代理(就像我在工作中一样),您不必弄乱 CPAN。

        【讨论】:

          【解决方案9】:

          如果你想学究气并保持在一行(不使用 use 语句和 shebang),那么我会从 tetromino 的回答中回过头来建议:

          print Dumper( { 'abc' => 123, 'def' => [4,5,6] } );
          

          除了使用匿名哈希来跳过临时变量之外,没有做任何特别的事情;)

          【讨论】:

          • OP 说他有“我的哈希”需要打印。这个答案本身就是聪明
          • OP 希望在一行中完成。只是展示了一种单行的方式。所以这值得投反对票吗?
          【解决方案10】:

          我为散列的每个元素添加一个空格以便清楚地看到它:

          print map {$_ . " "} %h, "\n";
          

          【讨论】:

            【解决方案11】:

            我真的很喜欢在一个内衬代码中对键进行排序:

            print "$_ => $my_hash{$_}\n" for (sort keys %my_hash);
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2019-01-13
              • 2013-01-30
              • 2014-07-22
              • 1970-01-01
              • 1970-01-01
              • 2013-05-31
              • 2015-07-17
              • 1970-01-01
              相关资源
              最近更新 更多