Merge Hashes和key获取旧值和新值

时间:2015-07-08 15:10:11

标签: arrays ruby recursion hash merge

想象一下,我有一个像这样的数组

array = [4,"hello",[[3],:d,7,[:a,"seven"]]]



class Array
  def deep_collect_by_elem_type_as_hash()
    e = {}
    self.each(){|x|
      if x.is_a?(Array)
        e.merge(x.deep_collect_by_elem_type_as_hash)
      end
      if !x.is_a?(Array)
        if e.has_key?(x.class)
          e[x.class]<<x
        else
          e[x.class] = [x]
        end
      end
    }
    return e
  end

我希望我的所有数组都创建一个哈希,其中包含包含我的Array中不同类的键。 它们的值将是每个类的实际元素。

所以它看起来像这样:

{Fixnum=>[4, 3, 7], String=>["hello", "seven"], Symbol=>[:d, :a]}

我想在没有使用展平的情况下解决整个事情,但要做到这一点。 Te flatten解决方案可能如下所示:

def deep_collect_by_elem_type_as_hash1()
    e = {}
    flat= self.flatten()
    flat.each(){|x|
      if e.has_key?(x.class)
        e[x.class]<<x
      else
        e[x.class] = [x]
      end
    }
    return e
  end

对于那些想知道为什么我不想使用flatten的人:我仍然有完全理解如何实现递归方法的问题,因此这是一个让我更好理解的问题。

我想我不知何故必须实现与块的合并,但我无法找出一个合适的块。 merge(x.deep_collect_by_elem_type_as_hash(){|k,v1,v2| help}

2 个答案:

答案 0 :(得分:2)

我们走了:

a = [4,"hello",[[3],:d,7,[:a,"seven"]]]

def stuff(a)
  res = {}
  a.each do |e|
    if e.is_a?(Array)
      stuff(e).each do |k,v|
        res[k] ||= []
        v.each {|x| res[k] << x}
      end
    else
      k = e.class
      res[k] ||= []
      res[k] << e
    end
  end
  res
end

puts stuff(a).inspect

如果你需要打开和扩展数组,你可以按照以下方式做点什么:

class Array
  def stuff(a = self)
  ...
  end
end

答案 1 :(得分:1)

你可以这样做:

def group_by_class(arr, h = Hash.new { |h,k| h[k] = [] })
  arr.each { |e| e.is_a?(Array) ? group_by_class(e,h) : h[e.class] << e }
  h
end

array = [4,"hello",[[3],:d,7,[:a,"seven"]]]
group_by_class(array)
  #=> {Fixnum=>[4, 3, 7], String=>["hello", "seven"], Symbol=>[:d, :a]}

array = [4,"hello",[[3],:d,7,[:a,"seven",["b",9,[:e,["cat", {a: 0}, 5]]]]]]
group_by_class(array)
  #=> {Fixnum=>[4, 3, 7, 9, 5], String=>["hello", "seven", "b", "cat"],
  #    Symbol=>[:d, :a, :e], Hash=>[{:a=>0}]} 

你也可以写:

def group_by_class(arr)
  arr.each { |e| e.is_a?(Array) ? group_by_class(e) : @h[e.class] << e }
end

@h = Hash.new { |h,k| h[k] = [] }
group_by_class(array)
@h
  #=> {Fixnum=>[4, 3, 7, 9, 5], String=>["hello", "seven", "b", "cat"],
  #    Symbol=>[:d, :a, :e], Hash=>[{:a=>0}]}