2012-10-02 67 views
0

真的不知道如何标题这个问题。可以使用&符号在Ruby中打印散列吗?

考虑一个任意哈希(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) 

回答

1

你可以避开两个块变量,并有一个代替这样做:

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

默认情况下,no。

做你想做什么,你需要一个方法添加到Array类,打印出你想要的方式,是这样的:

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

与,ENV.each(&:bar)会做你的期望。

这就是说,我不会推荐这个。添加到基类是只有当效用远远超过未来冲突的可能性时才应该做的事情,并且这种方法对于具有至少2个元素的数组非常专业化。

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

1

在您的示例中,使用&: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 } 

带有手柄吧,你可以通过&条代替块到像ENV这样的哈希。因此,考虑哈希,FOO:

foo.each(&bar) 

一个伟大的职位在这个问题上更多阅读:http://weblog.raganwald.com/2008/06/what-does-do-when-used-as-unary.html

1

在一般情况下,这是可能的,如果集合中的元素,以该方法作出回应。例如:

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"] 

此操作,因为&symbol是语法糖symbol.to_proc,这反过来又一些工作魔术以返回发送该消息到它接收作为参数的对象的块。

虽然这不会对你的工作,例如(因为在ENV的对象不以:bar响应),你可以通过一个已经使用&存储在一个变量块:

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