将具有共同值/键的数组转换为散列

时间:2012-04-12 23:15:31

标签: ruby arrays hash

我有一个像这样的数组:

[[1,"A"], [1,"B"], [2,"C"], [2,"D"]]

我想把结果变成哈希,就像这样:

1 => {results => ["A","B"]}, 2 => {results => ["C","D"]}

我尝试使用“group_by”方法,但无法将其置于此表单中。什么是最有效的方法?

有什么想法吗?

4 个答案:

答案 0 :(得分:2)

这是你想要的吗?

irb(main):001:0> a=[[1,"A"], [1,"B"], [2,"C"], [2,"D"]]
=> [[1, "A"], [1, "B"], [2, "C"], [2, "D"]]

irb(main):002:0> h={}
=> {}

irb(main):003:0> a.each { |k,v| h[k] ||= []; h[k] << v }
=> [[1, "A"], [1, "B"], [2, "C"], [2, "D"]]

irb(main):004:0> h
=> {1=>["A", "B"], 2=>["C", "D"]}

或者,如果你真的想要一个带有'result'键的散列表哈希表:

irb(main):003:0> a.each { |k,v| h[k] ||= {}; h[k]['result'] ||= []; h[k]['result'] << v }
=> [[1, "A"], [1, "B"], [2, "C"], [2, "D"]]
irb(main):004:0> h
=> {1=>{"result"=>["A", "B"]}, 2=>{"result"=>["C", "D"]}}

答案 1 :(得分:2)

对于一线情人:

a = [[1,"A"], [1,"B"], [2,"C"], [2,"D"]]
a.inject(Hash.new { |h, k| h[k] = {"results" => []} }) { |h, e| h[e.first]["results"] << e.last; h }

答案 2 :(得分:1)

我不确定你为什么要这个内在的'结果'字,但这里是如何得到你想要的:

the_list = [[1,"A"], [1,"B"], [2,"C"], [2,"D"]]
#=> [[1, "A"], [1, "B"], [2, "C"], [2, "D"]]

by_key = the_list.group_by(&:first)
#=> {1=>[[1, "A"], [1, "B"]], 2=>[[2, "C"], [2, "D"]]}

as_result_hash = by_key.map do |key, matches|
  [key, {'results'=>matches.map(&:last) }]
end
#=> [[1, {"results"=>["A", "B"]}], [2, {"results"=>["C", "D"]}]]

final = Hash[*as_result_hash.flatten(1)]
#=> {1=>{"results"=>["A", "B"]}, 2=>{"results"=>["C", "D"]}}

听起来你已经弄清楚了group_by的基本用法 - 你可以得到一组按一些键分组的结果。

下一步是将这些结果映射到您想要的格式。为此,我们只需映射by_key字典,返回原始密钥和映射结果。

这将返回一个数组,因此我们使用Hash[*array.flatten(1)]将其转换回字典。


如果你不需要内部'结果',你可以这样做:

as_result_hash = by_key.map do |key, matches|
  [key, matches.map(&:last)]
end
#=>  [[1, ["A", "B"]], [2, ["C", "D"]]]

答案 3 :(得分:1)

a = [[1,"A"], [1,"B"], [2,"C"], [2,"D"]]
Hash[a.group_by(&:first).map{ |k, v| [k, {"results" => v.map(&:last)}]}]