var*_*tis 29 ruby recursion hash ruby-on-rails ruby-on-rails-3
所以我有一个哈希,对于每个哈希级别,我想存储它的键和值.问题是,值可以是另一个哈希数组.此外,该哈希可以包含键值对,其中值又是另一个哈希数组等等.另外,我不知道每个哈希的嵌套程度有多深.举个例子:
{
:key1 => 'value1',
:key2 => 'value2',
:key3 => {
:key4 => 'value4',
:key5 => 'value5'
},
:key6 => {
:key7 => 'value7',
:key8 => {
:key9 => 'value9'
}
}
}
Run Code Online (Sandbox Code Playgroud)
..等等.我想要做的是保存每个键,值对和其父级的ID.我认为这可能是递归完成的,我只是不确定如何因为我不熟悉递归函数.我知道如何正常迭代数据:
myHash.each {|key, value|
...Do something with the key and value ...
}
Run Code Online (Sandbox Code Playgroud)
所以我猜测递归调用将是这样的:
def save_pair (myHash)
myHash.each {|key, value|
if(value.class != Hash) ? Pair.create(key, value) : save_pair(value)
}
end
Run Code Online (Sandbox Code Playgroud)
这是未经测试的,我仍然不确定如何合并保存父ID.
Mar*_*ins 21
如果我了解目标,那么您应该能够将父级传递给save方法.对于顶级,它将是零.以下显示了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
Run Code Online (Sandbox Code Playgroud)
以下是对它的示例调用:
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)
Run Code Online (Sandbox Code Playgroud)
seb*_*ian 10
我知道这是一个迟到的回复,但我只是为你的问题实现了一个非递归的解决方案,并认为值得分享.
class Hash
def deep_traverse(&block)
stack = self.map{ |k,v| [ [k], v ] }
while not stack.empty?
key, value = stack.pop
yield(key, value)
if value.is_a? Hash
value.each{ |k,v| stack.push [ key.dup << k, v ] }
end
end
end
end
Run Code Online (Sandbox Code Playgroud)
然后,回到原来的问题,您可以:
h = {
:key1 => 'value1',
:key2 => 'value2',
:key3 => {
:key4 => 'value4',
:key5 => 'value5'
},
:key6 => {
:key7 => 'value7',
:key8 => {
:key9 => 'value9'
}
}
}
h.deep_traverse{ |path,value| p [ path, value ] }
# => [[:key6], {:key7=>"value7", :key8=>{:key9=>"value9"}}]
# [[:key6, :key8], {:key9=>"value9"}]
# [[:key6, :key8, :key9], "value9"]
# [[:key6, :key7], "value7"]
# [[:key3], {:key4=>"value4", :key5=>"value5"}]
# [[:key3, :key5], "value5"]
# [[:key3, :key4], "value4"]
# [[:key2], "value2"]
# [[:key1], "value1"]
Run Code Online (Sandbox Code Playgroud)
还有一个要点版本.
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]
Run Code Online (Sandbox Code Playgroud)