如何将lambda传递给Hash.each?

时间:2013-02-21 00:20:49

标签: ruby lambda

如何将lambda传递给hash.each,以便重新使用某些代码?

> h = { a: 'b' }
> h.each do |key, value| end
 => {:a=>"b"}
> test = lambda do |key, value| puts "#{key} = #{value}" end 
> test.call('a','b')
a = b
> h.each &test
ArgumentError: wrong number of arguments (1 for 2)
  from (irb):1:in `block in irb_binding'
  from (irb):5:in `each'
  from (irb):5
  from /Users/jstillwell/.rvm/rubies/ruby-1.9.3-p362/bin/irb:16:in `<main>'
> h.each test
ArgumentError: wrong number of arguments(1 for 0)
  from (irb):8:in `each'
  from (irb):8
  from /Users/jstillwell/.rvm/rubies/ruby-1.9.3-p362/bin/irb:16:in `<main>'

3 个答案:

答案 0 :(得分:11)

each产生块的当前元素,因为lambda需要接受一个参数,而不是两个。在Hash的情况下,产生的元素是两个元素Array,第一个元素是键,第二个元素是值。

test = lambda do |el| puts "#{el.first} = #{el.last}" end
h.each &test
# a = b

或者,您可以使用Ruby支持在参数列表中解构bind:

test = lambda do |(k, v)| puts "#{k} = #{v}" end
h.each &test
# a = b

或者,不是使用具有相同参数绑定语义的lambda作为方法,而是可以使用Proc,它具有与块相同的参数绑定语义,即它将解包多个参数绑定中的单个Array参数:

test = proc do |k, v| puts "#{k} = #{v}" end
h.each &test
# a = b

答案 1 :(得分:0)

我仍然觉得这是不一致的语法,我在另一个问题中找到答案(但没有道歉) Inconsistency of arity between Hash.each and lambdas

我把它改为

lambda do |(key, value)|

然后我可以传入

hash.each &test

或者我可以直接用

来调用它
test.call([key, value])

如果有人有更好的答案,或者至少有一个简洁的借口,为什么这是必要的。我很乐意给他们分数。

答案 2 :(得分:0)

我遇到过类似的情况,我不想打印,而是在对值进行了一些操作之后返回键-值对...上述解决方案适用于您只想打印的情况,但是当您要打印时,可能会变得棘手您需要返回这些键值对的哈希值。所以我认为这可能会有所帮助

我用它来解决caesar-cipher难题

hash1 = {"a" => 1, "b" => 2, "c" => 3}
test = lambda {|k,v| true ? {k => v+2} : {k => v+1} }

将其映射到哈希之后,它将返回一个哈希数组(这是有趣的地方)

hash2 = hash1.map(&test)   # [{"a"=>3}, {"b"=>4}, {"c"=>5}]

我们可以将其转换为红宝石哈希!

hash2.inject(:merge!)   # {"a" => 3, "b" => 4, "c" => 5}

宾果!!!对?