2013-07-12 127 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