我有开始作为一个哈希:
{"request"=>{
"security"=>{"username"=>{"type"=>nil}, "password"=>{"type"=>nil}},
"order_i_d"=>{"type"=>nil, "description"=>nil},
"order_number"=>{"type"=>nil},
"show_kit_as_individual_s_k_us"=>false,
"website_i_d"=>{"type"=>nil, "description"=>nil}
}}
我想递归删除是nil?
和empty?
所有值,但留在原地的falsey
值。最终的结果应该是这样的:
{"request"=>{
"show_kit_as_individual_s_k_us"=>false
}}
我怎样才能做到这一点?
只是另一种实现,为乐趣和实践编写的。
DeepCompact.deep_compact(hash)
DeepCompact.deep_compact!(hash)
{ foo: nil }.extend(DeepCompact).deep_compact
using DeepCompact
到文件/类会带来deep_compact
和deep_compact!
到散列和数组在该文件/类的所有代码。这里的模块:
module DeepCompact
[Hash, Array].each do |klass|
refine klass do
def deep_compact
DeepCompact.deep_compact(self)
end
def deep_compact!
DeepCompact.deep_compact!(self)
end
end
end
def self.extended(where)
where.instance_exec do
def deep_compact
DeepCompact.deep_compact(self)
end
def deep_compact!
DeepCompact.deep_compact!(self)
end
end
end
def deep_compact(obj)
case obj
when Hash
obj.each_with_object({}) do |(key, val), obj|
new_val = DeepCompact.deep_compact(val)
next if new_val.nil? || (new_val.respond_to?(:empty?) && new_val.empty?)
obj[key] = new_val
end
when Array
obj.each_with_object([]) do |val, obj|
new_val = DeepCompact.deep_compact(val)
next if new_val.nil? || (new_val.respond_to?(:empty?) && new_val.empty?)
obj << val
end
else
obj
end
end
module_function :deep_compact
def deep_compact!(obj)
case obj
when Hash
obj.delete_if do |_, val|
val.nil? || (val.respond_to?(:empty?) && val.empty?) || DeepCompact.deep_compact!(val)
end
obj.empty?
when Array
obj.delete_if do |val|
val.nil? || (val.respond_to?(:empty?) && val.empty?) || DeepCompact.deep_compact!(val)
end
obj.empty?
else
false
end
end
module_function :deep_compact!
end
然后就如何使用它的一些例子:
hsh = {
'hello' => [
'world',
{ 'and' => nil }
],
'greetings' => nil,
'salutations' => {
'to' => { 'you' => true, 'him' => 'yes', 'her' => nil },
'but_not_to' => nil
}
}
puts "Original:"
pp hsh
puts
puts "Non-destructive module function:"
pp DeepCompact.deep_compact(hsh)
puts
hsh.extend(DeepCompact)
puts "Non-destructive after hash extended:"
pp hsh.deep_compact
puts
puts "Destructive refinement for array:"
array = [hsh]
using DeepCompact
array.deep_compact!
pp array
和输出:
Original:
{"hello"=>["world", {"and"=>nil}],
"greetings"=>nil,
"salutations"=>
{"to"=>{"you"=>true, "him"=>"yes", "her"=>nil}, "but_not_to"=>nil}}
Non-destructive module function:
{"hello"=>["world"], "salutations"=>{"to"=>{"you"=>true, "him"=>"yes"}}}
Non-destructive after hash extended:
{"hello"=>["world"], "salutations"=>{"to"=>{"you"=>true, "him"=>"yes"}}}
Destructive refinement for array:
[{"hello"=>["world"], "salutations"=>{"to"=>{"you"=>true, "him"=>"yes"}}}]
或者只是使用了多种宝石为你提供这种之一。
提出了以下几点:
class Hash
def deep_compact!
self.each_pair do |key, value|
if value.is_a?(Hash)
value.deep_compact!
end
if value.nil? || (value.is_a?(Hash) && value.empty?)
self.delete(key)
end
end
end
end
另外一个选项:
class Hash
def deep_transform(&block)
self.inject({}){|result, (key,value)|
value = if Hash === value
value.deep_transform(&block)
else
value
end
block.call(result,key,value)
result
}
end
def deep_compact
self.deep_transform do |result, key, value|
if value.nil? || (value.is_a?(Hash) && value.empty?)
# Don't Keep
else
result[key] = value
end
end
end
end