如何从多维数组创建哈希

时间:2017-02-16 14:39:16

标签: ruby hash

我有这些参数:

x=["room_adults_1", "room_childs_1", "room_adults_2", "room_childs_2"]

当我运行此代码时:

y = x.map { |x| x.match(/^(room)_(adults|childs)_(\d+)/)}
z = y.map { |x| [x[1],[x[2],[x[3].reverse,""]]]}

我得到这个数组:

 => [["room", ["adults", ["1", ""]]], ["room", ["childs", ["1", ""]]], ["room", ["adults", ["2", ""]]], ["room", ["childs", ["2", ""]]]]

我想将最后的结果转换为Hash。如果我使用z.to_h(折叠最后一个元素),我会获得{"room"=>["childs", ["2", ""]]}。但我想要像这样的哈希:

 {
    "room":{
     "adults":{[
      {"1": ""},
      {"2": ""}
     ]},
     "child":{[
      {"1": ""},
      {"2": ""}
     ]} 
    }
  }

我该怎么办?

3 个答案:

答案 0 :(得分:4)

x.map { |e| e.split '_' }
 .group_by(&:shift) # room
 .map { |k, v| [k, v.group_by(&:shift) # adults/children
                    .map { |k, v| [k, v.map { |e, *| {e => ""} } ] }
                    .to_h ] }
 .to_h

#⇒ {"room"=>{"adults"=>[{"1"=>""}, {"2"=>""}],
#            "childs"=>[{"1"=>""}, {"2"=>""}]}}

答案 1 :(得分:3)

在这种情况下,我更喜欢each_with_object

x = ["room_adults_1", "room_childs_1", "room_adults_2", "room_childs_2"]

export = x.each_with_object(Hash.new { |k, v| k[v] = Hash.new { |k, v| k[v] = [] } }) do |string, exp|
  room, type, id = string.split("_")
  exp[room][type] << {id => ""}
end

p export
# => {"room"=>{"adults"=>[{"1"=>""}, {"2"=>""}], "childs"=>[{"1"=>""}, {"2"=>""}]}}

答案 2 :(得分:2)

我认为所需的结果是

{:room=>{:adults=>[{:"1"=>""}, {:"2"=>""}], :childs=>[{:"1"=>""}, {:"2"=>""}]}} 

因为问题中给出的构造不是有效的Ruby对象,更不用说哈希了。

arr = ["room_adults_1", "room_childs_1", "room_adults_2", "room_childs_2"]

h = arr.map { |s| s.split('_')[1,2].map(&:to_sym) }.group_by(&:first)
  #=> {:adults=>[[:adults, :"1"], [:adults, :"2"]],
  #    :childs=>[[:childs, :"1"], [:childs, :"2"]]}

{ room: h.merge(h) { |k,a,_| a.map { |_,b| { b=>"" } } } }
  #=> {:room=>{:adults=>[{:"1"=>""}, {:"2"=>""}], :childs=>[{:"1"=>""}, {:"2"=>""}]}} 

如果要将字符串作为字符串而不是符号,请删除.map(&:to_sym)