2014-12-16 2 views
3

Я ищу умный способ собрать родительские ключи глубоко вложенного ключа и назначить их как значение. например ...Как рекурсивно собирать глубоко вложенные ключи с рубиновым хешем

взять хэш как ...

{ 
    :foo => { 
    :bar => { 
     :baz => 'a', 
     :bez => 'b', 
     :biz => 'c' 
    } 
    } 
} 

и создать хэш от него, как это ...

{ 
    :foo => { 
    :bar => { 
     :baz => [:foo, :bar, :baz], 
     :bez => [:foo, :bar, :bez], 
     :biz => [:foo, :bar, :biz] 
    } 
    } 
} 
+0

Пытались ли вы что-нибудь? –

+1

Что вы пробовали? Вы должны, по крайней мере, иметь возможность выпускать * unclever *. – meagar

ответ

2

Попробуйте рекурсивное решение:

# array of parent keys initially [] 
def nested(hash, keys = []) 
    # go through each key-value pair 
    hash.each do |key, val| 
    # if the value is a Hash, recurse and 
    # add the key to the array of parents 
    if val.is_a? Hash 
     nested(val, keys.push(key)) 
     # remove last parent when we're done 
     # with this pair 
     keys.pop 
    else 
     # if the value is not a Hash, set the 
     # value to parents + current key 
     hash[key] = keys + [key] 
    end 
    end 
end 
+2

Это мутирует 'hash', что может быть или не быть нормально. –

+0

это так просто и совместимо с ruby ​​1.9. я, очевидно, передумал ... – brewster

1

сделать рекурсивную функцию.

def recurse(h, acc=[]) 
    Hash[h.map { |key, value| 
    if value.is_a? Hash 
     [key, recurse(value, acc + [key])] 
    else 
     [key, acc + [key]] 
    end 
    }] 
    # You can use h.map {...}.to_h in Ruby 2.1+ 
end 

recurse({ 
    :foo => { 
    :bar => { 
     :baz => 'a', 
     :bez => 'b', 
     :biz => 'c' 
    } 
    } 
}) 
# => {:foo=> 
#  {:bar=> 
#   {:baz=>[:foo, :bar, :baz], 
#     :bez=>[:foo, :bar, :bez], 
#     :biz=>[:foo, :bar, :biz]}}} 
+0

Nice и clean, ft. –

1

Я предлагаю следующую рекурсию.

Код

def rehash(h, keys = []) 
    h.each_with_object({}) { |(k,v),g| 
    g[k] = case v 
      when Hash then rehash(v, keys+[k]) 
      else   (keys + [k])  
      end 
    } 
end 

Пример

h = { :foo => { 
     :bar => { 
      :baz => 'a', 
      :bez => 'b', 
      :biz => 'c' 
     } 
     } 
    } 

rehash(h) 
    #=> {:foo=> 
     {:bar=> 
      {:baz=>[:foo, :bar, :baz], 
      :bez=>[:foo, :bar, :bez], 
      :biz=>[:foo, :bar, :biz]}}} 
Смежные вопросы