Просто еще одна реализация, написанная для удовольствия и практики.
- Нет исправлений обезьян
- Работает с хэшами и массивами
- Может использоваться как функция модуля, например:
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"}}}]
Или просто используйте один из нескольких драгоценных камней, которые предоставляют это для вас.