Removing all empty elements from a hash / YAML?

前端 未结 20 1576
礼貌的吻别
礼貌的吻别 2020-12-07 15:35

How would I go about removing all empty elements (empty list items) from a nested Hash or YAML file?

相关标签:
20条回答
  • 2020-12-07 15:39

    In Simple one liner for deleting null values in Hash,

    rec_hash.each {|key,value| rec_hash.delete(key) if value.blank? } 
    
    0 讨论(0)
  • 2020-12-07 15:41

    I know this thread is a bit old but I came up with a better solution which supports Multidimensional hashes. It uses delete_if? except its multidimensional and cleans out anything with a an empty value by default and if a block is passed it is passed down through it's children.

    # Hash cleaner
    class Hash
        def clean!
            self.delete_if do |key, val|
                if block_given?
                    yield(key,val)
                else
                    # Prepeare the tests
                    test1 = val.nil?
                    test2 = val === 0
                    test3 = val === false
                    test4 = val.empty? if val.respond_to?('empty?')
                    test5 = val.strip.empty? if val.is_a?(String) && val.respond_to?('empty?')
    
                    # Were any of the tests true
                    test1 || test2 || test3 || test4 || test5
                end
            end
    
            self.each do |key, val|
                if self[key].is_a?(Hash) && self[key].respond_to?('clean!')
                    if block_given?
                        self[key] = self[key].clean!(&Proc.new)
                    else
                        self[key] = self[key].clean!
                    end
                end
            end
    
            return self
        end
    end
    
    0 讨论(0)
  • 2020-12-07 15:45

    Deep deletion nil values from a hash.

      # returns new instance of hash with deleted nil values
      def self.deep_remove_nil_values(hash)
        hash.each_with_object({}) do |(k, v), new_hash|
          new_hash[k] = deep_remove_nil_values(v) if v.is_a?(Hash)
          new_hash[k] = v unless v.nil?
        end
      end
    
      # rewrite current hash
      def self.deep_remove_nil_values!(hash)
        hash.each do |k, v|
          deep_remove_nil_values(v) if v.is_a?(Hash)
          hash.delete(k) if v.nil?
        end
      end
    
    0 讨论(0)
  • 2020-12-07 15:46

    works for both hashes and arrays

    module Helpers
      module RecursiveCompact
        extend self
    
        def recursive_compact(hash_or_array)
          p = proc do |*args|
            v = args.last
            v.delete_if(&p) if v.respond_to? :delete_if
            v.nil? || v.respond_to?(:"empty?") && v.empty?
          end
    
          hash_or_array.delete_if(&p)
        end
      end
    end
    

    P.S. based on someones answer, cant find

    usage - Helpers::RecursiveCompact.recursive_compact(something)

    0 讨论(0)
  • 2020-12-07 15:46

    The recursive version of https://stackoverflow.com/a/14773555/1519240 works, but not with HashWithIndifferentAccess or other classes that are kind of Hash..

    Here is the version I am using:

    def recursive_compact
      inject({}) do |new_hash, (k,v)|
        if !v.nil?
          new_hash[k] = v.kind_of?(Hash) ? v.recursive_compact : v
        end
        new_hash
      end
    end
    

    kind_of?(Hash) will accept more classes that are like a Hash.

    You can also replace inject({}) by inject(HashWithIndifferentAccess.new) if you want to access the new hash using both symbol and string.

    0 讨论(0)
  • 2020-12-07 15:48

    This one would delete empty hashes too:

    swoop = Proc.new { |k, v| v.delete_if(&swoop) if v.kind_of?(Hash);  v.empty? }
    hsh.delete_if &swoop
    
    0 讨论(0)
提交回复
热议问题