我想删除不同嵌套级别的空哈希。一旦删除了空哈希,我也想删除它的容器哈希。我该怎么做?
这是我想要处理的哈希:
{
"query"=>{"filtered"=>{
"query"=>{"bool"=>{}},
"filter"=>{"query"=>{"query_string"=>{
"fields"=>[["standard_analyzed_name", "standard_analyzed_message"]],
"query"=>"Arnold AND Schwarz"
}}}
}},
"sort"=>[{"total_interactions"=>{"order"=>"desc"}}]
}
以下是我没有删除空{"query"=>{"bool"=>{}}
部分的代码:
def compactify_hash(main_hash)
main_hash.each do |key, value|
if(value.class == Hash && !value.empty?)
compactify_hash(value)
elsif(value.class == Hash && value.empty?)
main_hash.delete(key)
end
end
return main_hash
end
答案 0 :(得分:4)
这里有一些问题:
compactify_hash!
命名。最重要的是,你永远不会检查你的递归紧凑哈希值,看看是否压缩了它们还清空了它们。在这里:
if(value.class == Hash && !value.empty?)
compactify_hash(value)
elsif(value.class == Hash && value.empty?)
main_hash.delete(key)
end
您需要在 value.empty?
之后检查compactify_hash(value)
。
你可以这样做:
def compactify_hash(main_hash)
main_hash.each_with_object({}) do |(k, v), h|
if(v.is_a?(Hash))
ch = compactify_hash(v)
h[k] = ch if(!ch.empty?)
elsif(v.is_a?(Array))
h[k] = v.map do |e|
e.is_a?(Hash) ? compactify_hash(e) : e
end
else
h[k] = v
end
end
end
答案 1 :(得分:3)
我假设对于任何哈希h
,您希望创建另一个哈希g
,它与h
相同,但g
中没有嵌套哈希将具有键值对[k,v]
,v.respond_to(:empty?)
和v.empty?
都返回true
。例如,如果h
中存在以下嵌套哈希:
{ a: { b: '', c: {}, d: [] }, e: 3 }
然后g
中相应的嵌套哈希将是:
{ e: 3 }
实际上,我们会“删除”键值对:b=> ''
,:c=> {}
和:d=> []
,因为''
,{}
和[]
所有人都回复:empty?
并且都是空的。这会将嵌套哈希减少为:
{ a: {}, e: 3 }
由于a
的值现在为空,我们删除该键值对,使g
中的嵌套哈希值等于:
{ e: 3 }
我相信这可以通过以下方式实现:
def remove(h)
loop do
h_new = remove_empties(h)
break h if h==h_new
h = h_new
end
end
def remove_empties(h)
h.each_with_object({}) do |(k,v),g|
case v
when Hash
g[k] = remove_empties(h[k]) unless v.empty?
else
g[k] = v unless v.respond_to?(:empty?) && v.empty?
end
end
end
对于您的哈希,我将其称为h
:
remove(h)
#=> {:query=>
# {:filtered=>
# {:filter=>
# {:query=>
# {:query_string=>
# {:fields=>
[["standard_analyzed_name", "standard_analyzed_message"]],
# :query=>"Arnold AND Schwarz"
# }
# }
# }
# }
# },
# :sort=>[
# {:total_interactions=>
# {:order=>"desc"}
# }
# ]
# }
请注意,重复执行递归,直到不再执行散列修改。