我输入的内容如下:
input = [['abc',['xyz','1.1']], ['abc',['xyz','1.2']],['def',['lmn','3.14']]]
我想将其转换为
{'abc'=>[{'xyz'=>'1.1'},{'xyz'=>'1.2'}],'def'=>[{'lmn'=>'3.14'}]}
最好的方法是什么?
答案 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]] }