Removing All Empty Elements from a Hash/Yaml

Removing all empty elements from a hash / YAML?

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

Removing empty values from an deeply nested Ruby hash

Try the below with recusrion:

def remove_blank(hash)
hash.each do |_, value|
if value.is_a? Hash
remove_blank(value)
elsif value.is_a?(Array) && value[0].is_a?(Hash)
remove_blank(value[0])
end
end.reject! {|_, value| value.nil? || (value.is_a?(Array) && value.reject(&:empty?).empty?) }
end

Best way to remove element from Ruby hash array in yaml

require 'yaml'
ip = '1.2.3.4'
port = 3333

hash = YAML.load_file('ips.yml')
puts "hash (before): #{hash.inspect}"
hash[ip].delete(port) # here you are deleting the port (3333) from the ip (1.2.3.4)
puts "hash (after): #{hash.inspect}"
File.open('ips.yml', 'w') { |f| YAML.dump(hash, f) }

# hash (before): {"69.39.239.151"=>[7777, 8677, 8777], "69.39.239.75"=>[9677, 9377], "209.15.212.147"=>[8477, 7777], "104.156.244.109"=>[9999], "1.2.3.4"=>[3333, 4444]}
# hash (after): {"69.39.239.151"=>[7777, 8677, 8777], "69.39.239.75"=>[9677, 9377], "209.15.212.147"=>[8477, 7777], "104.156.244.109"=>[9999], "1.2.3.4"=>[4444]}

Recursively removing `nil` and empty values from hash

Just another implementation, written for fun & practice.

  • No monkey patching
  • Works on Hashes and Arrays
  • Can be used as a module function like: DeepCompact.deep_compact(hash)
  • Also a destructive target modifying variant: DeepCompact.deep_compact!(hash)
  • Can be used by extending on an existing object: { foo: nil }.extend(DeepCompact).deep_compact
  • Can be used via refinements: adding using DeepCompact to a file/class will bring deep_compact and deep_compact! to Hashes and Arrays for all code in that file/class.

Here's the module:

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

And then some examples on how to use it:

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

And the output:

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"}}}]

Or just use one of the multiple gems that provide this for you.

remove the key and value in the params hash with ruby on rails

class Hash
def compact(opts={})
inject({}) do |new_hash, (k,v)|
if !v.blank?
new_hash[k] = opts[:recursive] && v.class == Hash ? v.compact(opts) : v
end
new_hash
end
end
end

hash = {
:first_name=> {
1=> "david",
2=> ""
},
:last_name=> {
1=> "david",
2=> ""
},
:role=> {
1=> "dev",
2=> ""
},
:bio=> {
1=> "commercial",
2=> ""
}
}


hash.compact(:recursive=>true)

will give

{
:first_name => {
1 => "david"
},
:last_name => {
1 => "david"
},
:role => {
1 => "dev"
},
:bio => {
1 => "commercial"
}
}

source: Removing all empty elements from a hash / YAML?

Remove elements from a hash array if a value matches a line in a text file

@Stefan is right, it's better practice to create a separate array with the lines you'd like to delete from the array:

urls_to_delete = []
File.open('views/investigated.txt').each do |line|
urls_to_delete.push(line)
end

Then use that array to remove the lines from the hash:

@org.each do |key,value|
value['items'].delete_if { |h| urls_to_delete.include?(h['html_url']) }
end

Tested it with your example and does exactly what you're trying to achieve.



Related Topics



Leave a reply



Submit