【问题标题】:Can ampersand be used to print a hash in Ruby?可以使用&符号在Ruby中打印哈希吗?
【发布时间】:2012-10-02 00:25:04
【问题描述】:

真的不知道如何命名这个问题。

考虑任意散列(ENV 方便):

ENV.each { |key, val| puts key + ': ' + val }
LC_MESSAGES: en_US.utf-8
LC_COLLATE: en_US.utf-8
PWD: /Users/baller/ive_fallen_and_i_cant_get_up
LC_MONETARY: en_US.utf-8

是否可以使用 &: 速记来做到这一点?

foo.each(&:bar)

【问题讨论】:

    标签: ruby arrays iterator


    【解决方案1】:

    您可以通过以下方式摆脱两个块变量并拥有一个:

    each{|kv| puts kv.join(": ")}
    

    【讨论】:

      【解决方案2】:

      默认情况下没有。

      要做你想做的事,你需要向 Array 类添加一个方法,它会按照你想要的方式打印出来,比如:

      class Array
        def bar
          puts "#{self[0]}: #{self[1]}"
        end
      end
      

      这样,ENV.each(&:bar) 将按照您的预期行事。

      也就是说,我不会推荐这个。仅当实用程序远远超过未来冲突的可能性时,才应添加到基类中,并且此方法高度专门用于其中至少有 2 个元素的数组。

      不相关,但通过+ 连接字符串比使用插值要慢得多。它不必要地创建了额外的对象。

      【讨论】:

        【解决方案3】:

        一般来说,如果集合的元素响应该方法,这是可能的。例如:

        class Foo
          attr_reader :bar
        
          def initialize(bar)
            @bar = bar
          end
        end
        
        foos = [Foo.new("one"), Foo.new("two"), Foo.new("three")]
        
        p foos.map(&:bar)  #=> ["one", "two", "three"]
        

        之所以可行,是因为&symbolsymbol.to_proc 的语法糖,这反过来又产生了一些魔力,返回一个块,该块将该消息作为参数接收到对象。

        虽然这不适用于您的示例(因为 ENV 中的对象不响应 :bar),但您可以使用 & 传递存储在变量中的块:

        block = lambda { |key, value| puts "#{key}: #{value}" }
        ENV.each(&block)
        

        【讨论】:

          【解决方案4】:

          在您的示例中,使用&:bar 代替块将导致在给定对象上调用#to_proc,在本例中为符号:bar。 Ruby 中 Symbol 的#to_proc 实现基本上将foo.each(&:bar) 扩展为foo.each { |i| i.bar }。由于哈希产生了两个参数,因此在此示例中,i 是键值 args 的数组。这就是为什么您必须扩展 Array(如 @x1a4 所述)以使您的哈希按预期处理 &:bar。

          作为替代方案,您可以创建自己的类来响应#to_proc,或者简单地将您的块实现为 Proc:

          class Bar
            def to_proc
              Proc.new { |key, val| puts key + ': ' + val }
            end
          end
          
          bar = Bar.new
          
          # or
          
          bar = Proc.new { |key, val| puts key + ': ' + val }
          

          使用 bar 句柄,您可以将 &bar 代替块传递给像 ENV 这样的哈希。所以给定一个哈希值,foo:

          foo.each(&bar)
          

          关于这个主题的更多阅读的好帖子:http://weblog.raganwald.com/2008/06/what-does-do-when-used-as-unary.html

          【讨论】:

            猜你喜欢
            • 2018-11-27
            • 1970-01-01
            • 2017-08-27
            • 2015-05-29
            • 2022-12-10
            • 2019-09-18
            • 2019-02-03
            • 2014-02-22
            • 2013-09-30
            相关资源
            最近更新 更多