Итак, у меня есть хэш, и для каждого уровня хэша я хочу хранить его ключ и значение. Проблема в том, что значение может быть другим хэш-массивом. Более того, этот хэш может содержать пары ключ-значение, где значение - это опять же другой хэш-массив, и так далее, и тому подобное. Кроме того, я не знаю, насколько глубоко вложен каждый хэш. Для примера:
{
: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
Это не проверено, и я все еще не знаю, как включить сохранение идентификаторов родителей.
Если я пойму цель, то вы сможете передать родителю свой метод сохранения. Для верхнего уровня это будет ноль. Далее показана идея, где 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)
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]
Это должно быть хорошо для 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