Ruby:更新Hash值的最简单方法是什么?

Mis*_*hko 44 ruby hash

说:

h = { 1 => 10, 2 => 20, 5 => 70, 8 => 90, 4 => 34 }
Run Code Online (Sandbox Code Playgroud)

我想将每个值更改vfoo(v),这h将是:

h = { 1 => foo(10), 2 => foo(20), 5 => foo(70), 8 => foo(90), 4 => foo(34) }
Run Code Online (Sandbox Code Playgroud)

实现这一目标的最优雅方式是什么?

Gar*_*eve 107

您可以使用update(别名merge!)使用块更新每个值:

hash.update(hash) { |key, value| value * 2 }
Run Code Online (Sandbox Code Playgroud)

请注意,我们正在有效地hash与自身合并.这是必需的,因为Ruby将调用块来解决碰撞的任何键的合并,将值设置为块的返回值.

  • 当您尝试在Rails中使用它时要小心,其中Hash实际上是HashWithIndifferentAccess,并且在处理传递给`update`和`merge`的块时具有不同的行为.大约一个月前,有人建议修改它:https://github.com/rails/rails/pull/7519 (3认同)
  • 在我的快速基准测试中,这甚至比`every`方法快20%! (2认同)
  • `Hash#update` 是 `Hash#merge!` 的别名。[这些文档](http://ruby-doc.org/core-2.2.0/Hash.html#method-i-update) 提到大多数文档使用 `merge!`。我个人更喜欢使用 merge!,因为我的思维停留在哈希模式,而当我看到“更新”时我不禁想到 ActiveRecord。 (2认同)

Max*_*nus 16

Rails添加了Hash#transform_values,所以你现在可以做{a:1, b:2, c:3}.transform_values{|v| foo(v)}

http://api.rubyonrails.org/classes/Hash.html#method-i-transform_values

  • @Alex ruby​​ 2.4.0将其添加为核心。https://ruby-doc.org/core-2.4.0/Hash.html#method-i-transform_values (3认同)

rub*_*nce 7

这样做:

h.each {|k, v| h[k] = foo(v)}
Run Code Online (Sandbox Code Playgroud)


And*_*imm 5

对于大型哈希,以下内容比@Dan Cheail略快,并且功能编程风格稍微强一些:

new_hash = Hash[old_hash.map {|key, value| key, foo(value)}]
Run Code Online (Sandbox Code Playgroud)

Hash#map创建一个键值对Hash.[]数组,并将对数组转换为哈希值.

  • 另外,在Ruby 1.8中,你可能需要用`[]`显式地包围`key,foo(value)` - 我遇到了语法错误. (2认同)