Rails合并两个哈希数组?

时间:2011-12-20 00:56:45

标签: ruby-on-rails ruby

我很难掌握合并两个哈希数组所需的逻辑,似乎我以某种不同的方式问过his question a while back,我也试过了一些其他的东西,比如这里提供的答案:merging arrays of hashes

任何理解这一点的帮助对我都有帮助。

假设我有以下数组,这是从方法本身输出的,所以你可以想象那些:timestampTime个对象

[
  {:timestamp=>2011-12-19 00:00:00 UTC},
  {:timestamp=>2011-12-19 01:00:00 UTC},
  {:timestamp=>2011-12-19 02:00:00 UTC},
  {:timestamp=>2011-12-19 03:00:00 UTC},
  {:timestamp=>2011-12-19 04:00:00 UTC},
  {:timestamp=>2011-12-19 05:00:00 UTC}
]

然后是一个像这样的附加数组,每个数组都有另一个值(但有时除了:count之外可能还有更多的值)

[
  {:timestamp=>2011-12-19 02:00:00 UTC, :count=>5},
  {:timestamp=>2011-12-19 04:00:00 UTC, :count=>21}
]

结果是这样的:

[
  {:timestamp=>2011-12-19 00:00:00 UTC},
  {:timestamp=>2011-12-19 01:00:00 UTC},
  {:timestamp=>2011-12-19 02:00:00 UTC, :count=>5},
  {:timestamp=>2011-12-19 03:00:00 UTC},
  {:timestamp=>2011-12-19 04:00:00 UTC, :count=>21},
  {:timestamp=>2011-12-19 05:00:00 UTC}
]

再次感谢您的帮助,我不知道为什么我无法找到适当的设计模式。

3 个答案:

答案 0 :(得分:24)

看起来你首先按时间戳分组,然后合并值:

(a1+a2).group_by{|h| h[:timestamp]}.map{|k,v| v.reduce(:merge)}

答案 1 :(得分:2)

a = [
  {:timestamp=>'2011-12-19 00:00:00 UTC'},
  {:timestamp=>'2011-12-19 01:00:00 UTC'},
  {:timestamp=>'2011-12-19 02:00:00 UTC'},
  {:timestamp=>'2011-12-19 03:00:00 UTC'},
  {:timestamp=>'2011-12-19 04:00:00 UTC'},
  {:timestamp=>'2011-12-19 05:00:00 UTC'}
]

b = [
  {:timestamp=>'2011-12-19 02:00:00 UTC', :count=>5},
  {:timestamp=>'2011-12-19 04:00:00 UTC', :count=>21}
]

result = a.inject([]) do |memo, v|
  if match = b.detect { |w| (w.to_a & v.to_a).any? }
    memo << match.merge(v)
  else
    memo << v
  end
end

p result

答案 2 :(得分:2)

由于您使用每个哈希的:timestamp属性作为其“键”,因此如果您实际将数组转换为以:timestamp属性为键的哈希值,则很容易:

h1 = Hash[a1.map{|h| [h[:timestamp], h]}]
h2 = Hash[a2.map{|h| [h[:timestamp], h]}]

然后,您想要的只是简化merge - 两个哈希(并且使用已添加的键):

p h1.merge(h2).values
# => [
#  {:timestamp=>"2011-12-19 00:00:00 UTC"},
#  {:timestamp=>"2011-12-19 01:00:00 UTC"},
#  {:timestamp=>"2011-12-19 02:00:00 UTC", :count=>5},
#  {:timestamp=>"2011-12-19 03:00:00 UTC"},
#  {:timestamp=>"2011-12-19 04:00:00 UTC", :count=>21},
#  {:timestamp=>"2011-12-19 05:00:00 UTC"}
#]