Removing all empty elements from a hash / YAML?
Use hsh.delete_if. In your specific case, something like: hsh.delete_if { |k, v| v.empty? }
You could add a compact method to Hash like this
class Hash
def compact
delete_if { |k, v| v.nil? }
end
end
or for a version that supports recursion
class Hash
def compact(opts={})
inject({}) do |new_hash, (k,v)|
if !v.nil?
new_hash[k] = opts[:recurse] && v.class == Hash ? v.compact(opts) : v
end
new_hash
end
end
end
compact_blank (Rails 6.1+)
If you are using Rails
(or a standalone ActiveSupport
), starting from version 6.1
, there is a compact_blank
method which removes blank
values from hashes.
It uses Object#blank?
under the hood for determining if an item is blank.
{ a: "", b: 1, c: nil, d: [], e: false, f: true }.compact_blank
# => { b: 1, f: true }
Here is a link to the docs and a link to the relative PR.
A destructive variant is also available. See Hash#compact_blank!
.
If you need to remove only nil
values,
please, consider using Ruby build-in Hash#compact
and Hash#compact!
methods.
{ a: 1, b: false, c: nil }.compact
# => { a: 1, b: false }
Rails 4.1 added Hash#compact and Hash#compact! as a core extensions to Ruby's Hash
class. You can use them like this:
hash = { a: true, b: false, c: nil }
hash.compact
# => { a: true, b: false }
hash
# => { a: true, b: false, c: nil }
hash.compact!
# => { a: true, b: false }
hash
# => { a: true, b: false }
{ c: nil }.compact
# => {}
Heads up: this implementation is not recursive. As a curiosity, they implemented it using #select
instead of #delete_if
for performance reasons. See here for the benchmark.
In case you want to backport it to your Rails 3 app:
# config/initializers/rails4_backports.rb
class Hash
# as implemented in Rails 4
# File activesupport/lib/active_support/core_ext/hash/compact.rb, line 8
def compact
self.select { |_, value| !value.nil? }
end
end