2011-12-06 15 views
5

यह प्रश्न this question के विपरीत है।एक हैश को नेस्टेड हैश में परिवर्तित करना

एक हैश की तरह

{ 
    [:a, :b, :c] => 1, 
    [:a, :b, :d] => 2, 
    [:a, :e] => 3, 
    [:f] => 4, 
} 

प्रत्येक कुंजी के लिए एक सरणी क्या सबसे अच्छा तरीका है एक नेस्टेड हैश में तरह

{ 
    :a => { 
     :b => {:c => 1, :d => 2}, 
     :e => 3, 
    }, 
    :f => 4, 
} 
+0

कुछ भी नहीं "पुनरावर्ती" उस के बारे में, कि सादे नेस्टेड है। –

+0

@dominikh विशेष हैश रिकर्सिव नहीं हो सकता है, लेकिन जो भी एल्गोरिदम इसे बनाने के लिए रिकर्सिव होगा। लेकिन मुझे लगता है कि आप जो कहते हैं वह समझ में आता है। मैंने इसे संपादित किया। – sawa

+3

आपने अभी तक क्या प्रयास किया है? आपके प्रयास किए गए समाधान के बारे में विशेष रूप से क्या काम नहीं कर रहा है? – maerics

उत्तर

4

यहाँ यह कन्वर्ट करने के लिए एक सतत समाधान, एक पुनरावर्ती एक है है कि यह देखते हुए पाठक के लिए एक अभ्यास के रूप में छोड़ा गया है:

def convert(h={}) 
    ret = {} 
    h.each do |k,v| 
    node = ret 
    k[0..-2].each {|x| node[x]||={}; node=node[x]} 
    node[k[-1]] = v 
    end 
    ret 
end 

convert(your_hash) # => {:f=>4, :a=>{:b=>{:c=>1, :d=>2}, :e=>3}} 
+0

धन्यवाद। आपका जवाब इसे पुनरावर्ती करने से काफी बेहतर है। यह बहुत अच्छा है। – sawa

+0

डिफ़ॉल्ट खाली हैश क्यों? 'H.each_with_object ({}) में बदलकर नोट करें। (के, वी), ret | 'आप पहली और आखिरी पंक्तियां छोड़ सकते हैं (हालांकि मुझे यकीन नहीं है कि' प्रत्येक_with_object' (v1.9 +) उपलब्ध था या नहीं जब आपने प्रश्न का उत्तर दिया)। आप निश्चित रूप से 'कमी' का भी उपयोग कर सकते हैं। –

1

पहले से ही एक अच्छा जवाब है, लेकिन मैंने इस पर काम किया पुनरावर्ती समाधान है, तो यहाँ यह है:

def to_nest(hash) 
    {}.tap do |nest| 
    hash.each_pair do |key, value| 
     nodes = key.dup 
     node = nodes.shift 
     if nodes.empty? 
     nest[node] = value 
     else 
     nest[node] ||= {} 
     nest[node].merge!({nodes => value}) 
     end 
    end 
    nest.each_pair do |key, value| 
     nest[key] = to_nest(value) if value.kind_of?(Hash) 
    end 
    end 
end 
3

कार्यात्मक पुनरावर्ती एल्गोरिदम:

require 'facets' 

class Hash 
    def nestify 
    map_by { |ks, v| [ks.first, [ks.drop(1), v]] }.mash do |key, pairs| 
     [key, pairs.first[0].empty? ? pairs.first[1] : Hash[pairs].nestify] 
    end 
    end 
end 

p {[:a, :b, :c]=>1, [:a, :b, :d]=>2, [:a, :e]=>3, [:f]=>4}.nestify 
# {:a=>{:b=>{:c=>1, :d=>2}, :e=>3}, :f=>4} 
0

एक और तरीका है:

def convert(h) 
    h.each_with_object({}) { |(a,n),f| f.update({ a.first=>(a.size==1 ? n : 
    convert({ a[1..-1]=>n })) }) { |_,ov,nv| ov.merge(nv) } } 
end 

यह प्रयास करें:

h = { 
    [:a, :b, :c] => 1, 
    [:a, :b, :d] => 2, 
    [:a, :e] => 3, 
    [:f] => 4, 
} 

convert(h) #=> {:a=>{:b=>{:d=>2}, :e=>3}, 
      # :f=>4} 
0

एक मिश्रित हैश के लिए/सरणी नेस्टेड संरचना आप वें उपयोग कर सकते हैं है। (सरणी के लिए भी संशोधित)

def unflatten(h={}) 
    ret = {} 
    h.each do |k,v| 
    node = ret 
    keys = k.split('.').collect { |x| x.to_i.to_s == x ? x.to_i : x } 
    keys.each_cons(2) do |x, next_d| 
     if(next_d.is_a? Fixnum) 
     node[x] ||= [] 
     node=node[x] 
     else 
     node[x] ||={} 
     node=node[x] 
     end 
    end                                                                   
    node[keys[-1]] = v 
    end 
    ret 
end 

बशर्ते आपने नीचे फ़्लैटिंग के लिए उपयोग किया हो। (सरणी के बजाय कुंजी के लिए अलग स्ट्रिंग डॉट [पर विभाजित करता है, तो आप की जरूरत है।])

def flatten_hash(hash) 
    hash.each_with_object({}) do |(k, v), h| 
    if v.is_a? Hash 
     flatten_hash(v).map do |h_k, h_v| 
     h["#{k}.#{h_k}"] = h_v 
     end 
    elsif v.is_a? Array 
     flatten_array(v).map do |h_k,h_v| 
     h["#{k}.#{h_k}"] = h_v 
     end 
    else 
     h[k] = v 
    end 
    end 
end 


def flatten_array(array) 
    array.each_with_object({}).with_index do |(v,h),i| 
    pp v,h,i 
    if v.is_a? Hash 
     flatten_hash(v).map do |h_k, h_v| 
     h["#{i}.#{h_k}"] = h_v 
     end 
    elsif v.is_a? Array 
     flatten_array(v).map do |h_k,h_v| 
     h["#{i}.#{h_k}"] = h_v 
     end 
    end 
    end 
end 
0

DeepEnumerable का उपयोग करना:

require DeepEnumerable 

h = {[:a, :b, :c]=>1, [:a, :b, :d]=>2, [:a, :e]=>3, [:f]=>4} 

h.inject({}){|hash, kv| hash.deep_set(*kv)} 
संबंधित मुद्दे