Isaac,我喜欢你使用递归的想法,因为它处理嵌套到任何级别的哈希。我想我理解你的代码为什么不起作用,以及如何修复它。这是你的代码:
def remove_hash_values(hash, target = nil)
hash.delete_if {|key, value| value == target}
hash.each_value {|obj| remove_hash_values(obj, target) if obj.is_a?(Hash)}
end
认为
hash = {a: 10, b: {c: 10}}
我们调用:
remove_hash_values(hash, 10)
我期待你想remove_hash_values(hash, 10)
回来{}
,但我相信它会回来{b: {}}
。让我们来看看计算:
remove_hash_values(hash, 10)
hash.delete_if {|key, value| value == target} # hash => {b: {c: 10}}
hash.each_value {|obj| remove_hash_values(obj, target) if obj.is_a?(Hash)} calls (next line)
remove_hash_values({c: 10})
hash.delete_if {|key, value| value == target} # hash => {}
hash.each_value {|obj| remove_hash_values(obj, target) if obj.is_a?(Hash)} # hash => {}
hash => {b: {}}
这就是我认为你可以做到的方式,尽管我还没有检查我的代码。首先假设target
不是一个hash
或另一个结构,只是一个简单的值。尝试这个:
def remove_hash_values(hash, target = nil)
hash.keys.each do |key|
value = hash[key]
case value
when Hash
val = remove_hash_values(hash[key], target)
if val == {}
hash.delete(key)
else
hash[key] = val
end
else
hash.delete(key) if val == target
end
end
hash
end
如果您想概括这一点,那么这target
可能是一个(可能是嵌套的)哈希,我认为这可能有效:
def remove_hash_values(hash, target = nil)
hash.keys.each do |key|
value = hash[key]
if value.is_a? Hash
if target.is_a? Hash && hash[key] == target
hash.delete(key)
next
end
else
# value is not a hash
hash.delete(key) if !(target.is_a? Hash) && if hash[key] == target)
next
end
# Value is a hash, target may or may not be a hash, value != target
val = remove_hash_values(hash[key], target)
if val == target
hash.delete(key)
else
hash(key)= val
end
end
hash
end