Следующий рекурсивный метод должен обеспечить желаемые результаты.
def combine_em(arr)
(k1, k2), (v1, v2) = arr.map(&:flatten).transpose
(k1==k2 && v1.is_a?(Hash)) ? { k1=>combine_em([v1, v2]) } :
{}.merge(*arr)
end
arr = [{"base"=>{"floor1"=>{"apt1"=>{"room"=>4}}}},
{"base"=>{"floor1"=>{"apt2"=>{"room"=>6}}}}]
combine_em arr
#=> {"base"=>{"floor1"=>{"apt1"=>{"room"=>4},
# "apt2"=>{"room"=>6}}}}
arr = [{"base"=>{"floor1"=>{"level1"=>{"apt1"=>{"room"=>4}}}}},
{"base"=>{"floor1"=>{"level1"=>{"apt2"=>{"room"=>6}}}}}]
combine_em arr
#=> {"base"=>{"floor1"=>{"level1"=>{"apt1"=>{"room"=>4},
# "apt2"=>{"room"=>6}}}}}
arr = [{"base"=>{"floor1"=>{"apt1"=>{"room"=>4}}}},
{"base"=>{"floor2"=>{"apt1"=>{"room"=>6}}}}]
combine_em arr
#=> {"base"=>{"floor1"=>{"apt1"=>{"room"=>4}},
# "floor2"=>{"apt1"=>{"room"=>6}}}}
arr = [{"base"=>{"floor1"=>{"apt1"=>{"room1"=>4}}}},
{"base"=>{"floor1"=>{"apt1"=>{"room2"=>6}}}}]
combine_em arr
#=> {"base"=>{"floor1"=>{"apt1"=>{"room1"=>4,
# "room2"=>6}}}}
arr = [{"base1"=>{"floor1"=>{"apt1"=>{"room"=>4}}}},
{"base2"=>{"floor2"=>{"apt1"=>{"room"=>6}}}}]
combine_em arr
#=> {"base1"=>{"floor1"=>{"apt1"=>{"room"=>4}}},
# "base2"=>{"floor2"=>{"apt1"=>{"room"=>6}}}}
arr = [{"base"=>{"floor1"=>{"apt1"=>{"room"=>4}}}},
{"base"=>{"floor1"=>{"apt1"=>{"room"=>6}}}}]
combine_em arr
#=> {"base"=>{"floor1"=>{"apt1"=>{"room"=>6}}}}
Последний пример arr
(если это могло произойти) может не дать желаемого результата.Если это так, то в этом случае необходимо будет указать требуемое возвращаемое значение.
Hash # merge был изменен в Ruby v2.6, чтобы разрешить несколько аргументов, поэтому мы можем теперьнапишите
arr = [{:a=>1}, {:b=>2}, {:c=>3}]
{}.merge(*arr)
#=> {:a=>1, :b=>2, :c=>3}
Для поддержки более ранних версий Ruby напишите
arr.reduce(&:merge)
, что является сокращением для
arr.reduce { |h,g| h.merge(g) }
См. Enumerable # уменьшите (он же inject
).
Чтобы получить полное представление о том, как работает рекурсия, может потребоваться засолить метод с помощью операторов puts
.