在Ruby中将多维数组转换为Hash

时间:2017-03-10 13:42:16

标签: arrays ruby

我输入的内容如下:

input = [['abc',['xyz','1.1']], ['abc',['xyz','1.2']],['def',['lmn','3.14']]]

我想将其转换为

{'abc'=>[{'xyz'=>'1.1'},{'xyz'=>'1.2'}],'def'=>[{'lmn'=>'3.14'}]}

最好的方法是什么?

3 个答案:

答案 0 :(得分:8)

您可以使用each_with_object

accumulator = Hash.new { |k,v| k[v] = [] }

input.each_with_object(accumulator) {|(f, s), memo| memo[f] << Hash[*s] }
#=> {"abc"=>[{"xyz"=>"1.1"}, {"xyz"=>"1.2"}], "def"=>[{"lmn"=>"3.14"}]}

答案 1 :(得分:3)

另一种方法:

input.inject({}) { |a, (k, v)| a.merge(k => [Hash[*v]]) { |_, o, n| o + n } }

Ilya指出,merge!应优先于merge,因为它具有更好的性能特征。

答案 2 :(得分:1)

这是另一种选择:

accumulated = {}

input.each { |k, v| accumulated[k]&.push(Hash[*v]) || accumulated[k] = [Hash[*v]] }

#=> accumulated
#=> {"abc"=>[{"xyz"=>"1.1"}, {"xyz"=>"1.2"}], "def"=>[{"lmn"=>"3.14"}]}

如果您正在使用Rails,如果您发现它更具可读性,则可以将安全导航操作符(&)替换为try()

input.each { |k, v| accumulated[k].try(:push, Hash[*v]) || accumulated[k] = [Hash[*v]] }