如何总结嵌套数组中的值

时间:2016-05-11 08:18:16

标签: ruby

我有一个以下格式的数组:

arr = [
 ["OMAA002S16001006 1088", 13],
 ["OMAA002S16001006 1088", 13],
 ["OMAA002S16001006 1088", 10],
 ["OMRA001S16116037 1001", 10],
 ["OMRA001S16116037 0110", 9],
 ["OMAA002S16001014 0119", 9],
 ["OMAA002S16001002 0134", 9]
]

第一个条目是相同的代码,但编号不同。什么是使条目独特并总结右边值的最佳方法?结果应该是这样的:

[
 ["OMAA002S16001006 1088", 36],
 ["OMRA001S16116037 1001", 10],
 ["OMRA001S16116037 0110", 9],
 ["OMAA002S16001014 0119", 9],
 ["OMAA002S16001002 0134", 9]
]

5 个答案:

答案 0 :(得分:8)

使用Enumerable#each_with_object

arr.each_with_object(Hash.new(0)) { |(k, v), h| h[k] += v }
#=> {"OMAA002S16001006 1088"=>36,
#    "OMRA001S16116037 1001"=>10,
#    "OMRA001S16116037 0110"=>9,
#    "OMAA002S16001014 0119"=>9,
#    "OMAA002S16001002 0134"=>9}

您可以致电to_a将其转换回数组。

答案 1 :(得分:5)

使用group_bymapreduce

arr.group_by(&:first).map { |k, v| [k, v.map(&:last).reduce(:+)] }
#=> [["OMAA002S16001006 1088", 36],
#    ["OMRA001S16116037 1001", 10],
#    ["OMRA001S16116037 0110", 9],
#    ["OMAA002S16001014 0119", 9],
#    ["OMAA002S16001002 0134", 9]]

答案 2 :(得分:1)

这样的事情可能有所帮助:

arr.map.with_object(Hash.new(0)) { |(k, v), o| o[k] += v}.to_a
#=> [["OMAA002S16001006 1088", 36],
#    ["OMRA001S16116037 1001", 10],
#    ["OMRA001S16116037 0110", 9],
#    ["OMAA002S16001014 0119", 9],
#    ["OMAA002S16001002 0134", 9]]

答案 3 :(得分:0)

arr.each_with_object({}) { |(s,v), h| h.update(s=>v) { |_,o,n| o+n } }.to_a
  #=> [["OMAA002S16001006 1088", 36],
  #    ["OMRA001S16116037 1001", 10],
  #    ["OMRA001S16116037 0110", 9],
  #    ["OMAA002S16001014 0119", 9],
  #    ["OMAA002S16001002 0134", 9]] 

这使用Hash#update(aka merge!)的形式,它使用块(此处为{ |_,o,n| o+n })来确定合并的两个哈希中存在的键的值。请参阅文档了解on代表的内容。

请注意

arr.each_with_object({}) { |(s,v), h| h.update(s=>v) { |_,o,n| o+n } }
  #=> {"OMAA002S16001006 1088"=>36,
  #    "OMRA001S16116037 1001"=>10,
  #    "OMRA001S16116037 0110"=>9,
  #    "OMAA002S16001014 0119"=>9,
  #    "OMAA002S16001002 0134"=>9}
然后

.to_a将此哈希值转换为所需的数组数组。

我不是在倡导这种方法。我倾向于@ Stefan使用计数哈希。

答案 4 :(得分:0)

只需使用reduceto_a

arr.reduce(Hash.new(0)) { |h, (k,v)| h[k] += v; h }.to_a
#=> [["OMAA002S16001006 1088", 36],
#    ["OMRA001S16116037 1001", 10],
#    ["OMRA001S16116037 0110", 9],
#    ["OMAA002S16001014 0119", 9],
#    ["OMAA002S16001002 0134", 9]]