开发者

Recursively merge multidimensional arrays, hashes and symbols

开发者 https://www.devze.com 2022-12-20 14:49 出处:网络
I need a chunk of Ruby co开发者_如何学Gode to combine an array of contents like such: [{:dim_location=>[{:dim_city=>:dim_state}]},

I need a chunk of Ruby co开发者_如何学Gode to combine an array of contents like such:

[{:dim_location=>[{:dim_city=>:dim_state}]},
 :dim_marital_status, 
 {:dim_location=>[:dim_zip, :dim_business]}]

into:

[{:dim_location => [:dim_business, {:dim_city=>:dim_state}, :dim_zip]},
 :dim_marital_status]

It needs to support an arbitrary level of depth, though the depth will rarely be beyond 8 levels deep.


Revised after comment:

source = [{:dim_location=>[{:dim_city=>:dim_state}]}, :dim_marital_status, {:dim_location=>[:dim_zip, :dim_business]}]

expected = [{:dim_location => [:dim_business, {:dim_city=>:dim_state}, :dim_zip]}, :dim_marital_status]

source2 = [{:dim_location=>{:dim_city=>:dim_state}}, {:dim_location=>:dim_city}]  

def merge_dim_locations(array)
  return array unless array.is_a?(Array)
  values = array.dup
  dim_locations = values.select {|x| x.is_a?(Hash) && x.has_key?(:dim_location)}
  old_index = values.index(dim_locations[0]) unless dim_locations.empty?
  merged = dim_locations.inject({}) do |memo, obj| 
    values.delete(obj)
    x = merge_dim_locations(obj[:dim_location])
    if x.is_a?(Array) 
      memo[:dim_location] = (memo[:dim_location] || []) + x
    else
      memo[:dim_location] ||= []
      memo[:dim_location] << x
    end
    memo
  end
  unless merged.empty?
    values.insert(old_index, merged)
  end
  values
end


puts "source1:"
puts source.inspect
puts "result1:"
puts merge_dim_locations(source).inspect
puts "expected1:"
puts expected.inspect

puts "\nsource2:"
puts source2.inspect
puts "result2:"
puts merge_dim_locations(source2).inspect


I don't think there's enough detail in your question to give you a complete answer, but this might get you started:

class Hash
  def recursive_merge!(other)
    other.keys.each do |k|
      if self[k].is_a?(Array) && other[k].is_a?(Array)
        self[k] += other[k]
      elsif self[k].is_a?(Hash) && other[k].is_a?(Hash)
        self[k].recursive_merge!(other[k])
      else
        self[k] = other[k]
      end
    end
    self
  end
end
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号