2017-02-16 2 views
0

У меня есть этот Params:Как создать хэш из многомерного массива

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", ""]]]] 

Я хотел бы преобразовать этот последний результат в хэш. Если я использую z.to_h (свернуть последний элемент), я получаю {"room"=>["childs", ["2", ""]]}. Но я хотел бы, чтобы Хеш вот так:

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

Как я могу это сделать?

+0

@lcguida ... stackoverflow e l'inglese: P – sirion1987

+0

Хэш, который вы хотите, не является хешем. Это не действительный объект Ruby. –

+0

Для детей/взрослых: {[...]}? – sirion1987

ответ

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"=>""}]}} 
+2

отличный ответ, хотя 'dup' не требуется, так как' map' вернет копию в любом случае. Также я бы поставил точки в конце предыдущих строк, так что это фактический код – engineersmnky

+0

Вы гений: D – sirion1987

+0

Переменная «x», исходящая от Params. Чтобы присвоить правильное значение хешу, используйте: params ["room _ # {k} _ # {f.first}"] – sirion1987

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

Я предполагаю, что желаемый результат

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

как конструкт данные в вопросе не является допустимым объектом рубин, не говоря уже о хэш.

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).

Смежные вопросы