2013-07-12 128 views
3

我想展开嵌套散列到数组。例如:将嵌套散列展平到阵列

a = {'1'=>{'2'=>{'5'=>{},'6'=>{'8'=>{}}}},'3'=>{},'4'=>{'7'=>{}}} 

和flatten_nested_hash的结果(一)将是:

["1", "2", "5", "6", "8", "3", "4", "7"] 

最后我写了一些递归函数,但我觉得必须有这样的一些比较容易的,非递归的方式它。

我的功能看起来是这样的:

def flatten_nested_hash(categories) 
    categories.map do |k,v| 
     if v == {} 
     k 
     else 
     [k,flatten_nested_hash(v)] 
     end 
    end.flatten 
    end 
+0

@ raam86 PHP和Ruby是完全不同的语言。可能有重复的地方,但绝对不是那个。 – Mischa

+0

@米沙我完全同意。必须说我自己太懒惰以至于无法生成评论。固定。 – raam86

+0

http://stackoverflow.com/questions/16047106/getting-to-the-bottom-of-a-multidimensional-array-of-objects可以给这个问题另一个观点 – raam86

回答

12

递归。

def flatten_nested_hash(categories) 
    categories.flat_map{|k, v| [k, *flatten_nested_hash(v)]} 
end 

在Hash类中定义它。

class Hash 
    def flatten_nested; flat_map{|k, v| [k, *v.flatten_nested]} end 
end 
3

这是一个嵌套的数据结构 - 您将不得不使用某种递归或迭代方法来提取所有键。这比你有什么更容易一点,但:

def deep_extract_keys(hash) 
    hash.keys + hash.values.flat_map {|value| deep_extract_keys value } 
end 

p deep_extract_keys({"1"=>{"2"=>{"5"=>{}, "6"=>{"8"=>{}}}}, "3"=>{}, "4"=>{"7"=>{}}}) 

这是一个广度优先搜索,而不是深度优先搜索,所以输出:

["1", "3", "4", "2", "5", "6", "8", "7"] 
+2

这改变了元素的顺序。 – sawa

+0

是的,因为它的宽度优先。 :) –

0

这不是(明确地)递归和仅适用于非负整数键:

a.to_s.scan(/\d+/).map(&:to_i) # [1, 2, 5, 6, 8, 3, 4, 7] 

:-)

5

使用Ruby 2.1的d稍后,您可以使用优化将方法添加到Hash,并仅将它暴露给您需要的模块/类。

module HashRefinements 
    refine Hash do 
    def flatten_nested 
     flat_map { |k, v| [k, *v.flatten_nested] } 
    end 
    end 
end 

在你的类/模块

class MyThing 
    using HashRefinements 

    ... 

    def flatten_categories 
    categories.flatten_nested 
    end 

    ... 
end 
0
module Flattener 
    def deep_flatten 
    flatten.map do |item| 
     case item 
     when Hash, Array 
     item.deep_flatten 
     else 
     item 
     end 
    end.flatten 
    end 
end 

class Hash 

    include Flattener 

end 

class Array 

    include Flattener 

end