想象一下,我有一个像这样的数组
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}
答案 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}]}