要散列的哈希数组

evf*_*qcg 63 ruby arrays hash

例如,我有一些单个哈希值

a = [{a: :b}, {c: :d}]
Run Code Online (Sandbox Code Playgroud)

将它转换成这个的最佳方法是什么?

{a: :b, c: :d}
Run Code Online (Sandbox Code Playgroud)

How*_*ard 116

你可以用

a.reduce Hash.new, :merge
Run Code Online (Sandbox Code Playgroud)

直接产生

{:a=>:b, :c=>:d}
Run Code Online (Sandbox Code Playgroud)

请注意,在发生碰撞的情况下,订单很重要.后置哈希覆盖以前的映射,请参阅例如:

[{a: :b}, {c: :d}, {e: :f, a: :g}].reduce Hash.new, :merge   # {:a=>:g, :c=>:d, :e=>:f}
Run Code Online (Sandbox Code Playgroud)

  • `Hash.new`,或者像朋友一样打电话给他,`{}`:-)就像我喜欢纯粹的功能解决方案一样,请注意`merge`会在每次迭代时创建一个新的哈希值; 我们可以使用`update`代替它(它不会搞乱输入哈希值,这是重点):`hs.reduce({},:update)` (35认同)

pot*_*hin 38

你可以使用.inject:

a.inject(:merge)
#=> {:a=>:b, :c=>:d}
Run Code Online (Sandbox Code Playgroud)

示范

它从两个合并的每次迭代中启动一个新的哈希.为了避免这种情况,你可以使用破坏性的:merge!(或者:update,它是相同的):

a.inject(:merge!)
#=> {:a=>:b, :c=>:d}
Run Code Online (Sandbox Code Playgroud)

示范


tok*_*and 21

这两个:

total_hash = hs.reduce({}) { |acc_hash, hash| acc_hash.merge(hash) }
total_hash = hs.reduce({}, :merge)
Run Code Online (Sandbox Code Playgroud)

请注意,Hash#merge在每次迭代时都会创建一个新哈希,如果要构建一个大哈希,这可能会有问题.在这种情况下,请update改用:

total_hash = hs.reduce({}, :update)
Run Code Online (Sandbox Code Playgroud)

另一种方法是将哈希转换为对,然后构建最终哈希:

total_hash = hs.flat_map(&:to_a).to_h
Run Code Online (Sandbox Code Playgroud)


小智 5

我遇到了这个答案,我想在性能方面比较这两个选项,看看哪个更好:

  1. a.reduce Hash.new, :merge
  2. a.inject(:merge)

使用 ruby​​ 基准测试模块,结果表明选项 (2)a.inject(:merge)更快。

用于比较的代码:

require 'benchmark'

input = [{b: "c"}, {e: "f"}, {h: "i"}, {k: "l"}]
n = 50_000

Benchmark.bm do |benchmark|
  benchmark.report("reduce") do
    n.times do
      input.reduce Hash.new, :merge
    end
  end

  benchmark.report("inject") do
    n.times do
      input.inject(:merge)
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

结果是

       user     system      total        real
reduce  0.125098   0.003690   0.128788 (  0.129617)
inject  0.078262   0.001439   0.079701 (  0.080383)
Run Code Online (Sandbox Code Playgroud)

  • 这个结果让我很困惑。[文档](https://docs.ruby-lang.org/en/2.6.0/Enumerable.html#method-i-inject)说“reduce”和“inject”是别名。快速检查您的测试表明速度减慢是由于“Hash.new”作为初始值设定项造成的。`:merge` 每次迭代都会创建一个新的哈希值。`:update` 没有。因此,使用 `:update` 重新运行表明,即使使用 `Hash.new`,`:update` 版本也更快:``` 用户系统总实际减少量 w/ Hash.new & :update 0.056754 0.002097 0.058851 ( 0.059330) 减少 w/ :仅合并 0.090021 0.001081 0.091102 ( 0.091257)``` (2认同)