Итерация по глубоко вложенным уровням хэшей в Ruby

Итак, у меня есть хэш, и для каждого уровня хэша я хочу хранить его ключ и значение. Проблема в том, что значение может быть другим хэш-массивом. Более того, этот хэш может содержать пары ключ-значение, где значение - это опять же другой хэш-массив, и так далее, и тому подобное. Кроме того, я не знаю, насколько глубоко вложен каждый хэш. Для примера:

{
  :key1 => 'value1',
  :key2 => 'value2',
  :key3 => {
     :key4 => 'value4',
     :key5 => 'value5'
   },
    :key6 => {
      :key7 => 'value7',
      :key8 => {
        :key9 => 'value9'
      }
    }
  }

... И так далее. Что я хочу сделать, так это сохранить каждую пару ключ-значение и id ее родителя. Я понимаю, что это, вероятно, будет сделано рекурсивно, я просто не знаю как, потому что я не знаком с рекурсивными функциями. Я знаю, как перебирать данные обычным образом:

  myHash.each {|key, value|
    ...Do something with the key and value ...
  }

И поэтому я предполагаю, что рекурсивный вызов будет выглядеть примерно так:

def save_pair (myHash)
  myHash.each {|key, value|
    if(value.class != Hash) ? Pair.create(key, value) : save_pair(value)
  }
end

Это не проверено, и я все еще не знаю, как включить сохранение идентификаторов родителей.

28
задан malana 12 July 2017 в 10:20
поделиться

3 ответа

Если я пойму цель, то вы сможете передать родителю свой метод сохранения. Для верхнего уровня это будет ноль. Далее показана идея, где puts используется в качестве заполнителя для «сохранения».

def save_pair(parent, myHash)
  myHash.each {|key, value|
    value.is_a?(Hash) ? save_pair(key, value) :
            puts("parent=#{parent.nil? ? 'none':parent}, (#{key}, #{value})")
  }
end

Вот пример обращения к нему:

hash = Hash.new
hash["key1"] = "value1"
hash["key2"] = "value2"
hash["key3"] = Hash.new
hash["key3"]["key4"] = "value4"
hash["key3"]["key5"] = "value5"
hash["key6"] = Hash.new
hash["key6"]["key7"] = "value7"
hash["key6"]["key8"] = Hash.new
hash["key6"]["key8"]["key9"] = "value9"

save_pair(nil, hash)
21
ответ дан 28 November 2019 в 03:33
поделиться
class Hash
  def each_with_parent(parent=nil, &blk)
    each do |k, v|
      Hash === v ? v.each_with_parent(k, &blk) : blk.call([parent, k, v])
    end
  end
end

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

h.each_with_parent { |i| p i }
# [nil, :a, 1]
# [:b, :c, 3]
# [:b, :d, 4]
# [:e, :f, 5]
5
ответ дан 28 November 2019 в 03:33
поделиться

Это должно быть хорошо для JSON. Незначительные улучшения в коде Марка, где он преобразует все в верхний регистр в данном хэше:

def capitalize_hash(myHash)
    myHash.each {|key, value|
        puts "isHash: #{value.is_a?(Hash)}: " + value.to_s
        value.is_a?(Hash) ? capitalize_hash(value) : ( value.is_a?(Array) ? (myHash[key] = capitalize_array(value)) : (myHash[key] = value.try(:upcase)))
    }
end

def capitalize_array(myArray)
    myArray.each {|value|
        puts "isHash: #{value.is_a?(Hash)}: " + value.to_s
        value.is_a?(Array) ? capitalize_array(value) : ( value.is_a?(Hash) ? capitalize_hash(value) : value.try(:upcase))
    }
end
0
ответ дан 28 November 2019 в 03:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: