5

如何将 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>'
4

3 回答 3

12

each将当前元素生成到块中,因此 lambda 需要一个参数,而不是两个。如果产生Hash的元素是双元素Array,第一个元素是键,第二个元素是值。

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

或者,您可以使用 Ruby 对参数列表中的解构绑定的支持:

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

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

test = proc do |k, v| puts "#{k} = #{v}" end
h.each &test
# a = b
于 2013-02-21T00:32:05.840 回答
1

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

我把它切换到

lambda do |(key, value)|

然后我可以通过

hash.each &test

或者我可以直接调用它

test.call([key, value])

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

于 2013-02-21T00:29:55.537 回答
0

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

我用它来解决凯撒密码难题

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

我们可以将其转换为 ruby​​stically 哈希!

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

答对了!!!对?

于 2020-03-15T02:37:56.023 回答