如何以递归方式从(YAML)哈希中删除具有空值的所有键?

juw*_*ter 8 ruby hash yaml ruby-on-rails

我一直试图摆脱我的YAML文件中具有空(空白)值或空哈希作为值的所有哈希键.

这个早期的帖子帮我把它弄得差不多,但是只要有足够深的嵌套,递归的一行就会留下我的YAML转储空哈希.

我真的很感激任何帮助.谢谢!

proc = Proc.new { |k, v| (v.kind_of?(Hash) && !v.empty? ) ? (v.delete_if(&proc); nil) : v.blank? }

hash = {"x"=>{"m"=>{"n"=>{}}}, 'y' => 'content'}
hash.delete_if(&proc)
Run Code Online (Sandbox Code Playgroud)

实际输出

 {"x"=>{"m"=>{}}, "y"=>"content"} 
Run Code Online (Sandbox Code Playgroud)

期望的输出

{"y"=>"content"}
Run Code Online (Sandbox Code Playgroud)

saw*_*awa 14

class Hash
  def delete_blank
    delete_if{|k, v| v.empty? or v.instance_of?(Hash) && v.delete_blank.empty?}
  end
end

p hash.delete_blank
# => {"y"=>"content"}
Run Code Online (Sandbox Code Playgroud)


小智 5

这是一个更通用的方法:

class Hash
  def deep_reject(&blk)
    self.dup.deep_reject!(&blk)
  end

  def deep_reject!(&blk)
    self.each do |k, v|
      v.deep_reject!(&blk)  if v.is_a?(Hash)
      self.delete(k)  if blk.call(k, v)
    end
  end
end

{ a: 1, b: nil, c: { d: nil, e: '' } }.deep_reject! { |k, v| v.blank? }
==> { a: 1 }
Run Code Online (Sandbox Code Playgroud)