递归合并多维数组,散列和符号

时间:2010-02-16 23:48:00

标签: ruby hash merge multidimensional-array

我需要一大堆Ruby代码来组合这样的内容数组:

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

成:

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

它需要支持任意级别的深度,但深度很少超过8级。

2 个答案:

答案 0 :(得分:1)

评论后修改:

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

答案 1 :(得分:0)

我不认为你的问题中有足够的细节可以给你一个完整的答案,但这可能会让你开始:

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