Удалить все пустые элементы из хеша /YAML?

Как мне удалить все пустые элементы (пустые элементы списка) из вложенного файла Hash или YAML?

114 голосов | спросил Brian Jordan 10 PM00000070000004231 2010, 19:30:42

8 ответов


0

Вы можете добавить компактный метод в Hash следующим образом

class Hash
  def compact
    delete_if { |k, v| v.nil? }
  end
end

или для версии, которая поддерживает рекурсию

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
ответил opsb 8 FebruaryEurope/MoscowbFri, 08 Feb 2013 17:22:47 +0400000000pmFri, 08 Feb 2013 17:22:47 +040013 2013, 17:22:47
0

Используйте hsh.delete_if , В вашем конкретном случае что-то вроде: hsh.delete_if { |k, v| v.empty? }

ответил jpemberthy 10 PM00000070000001631 2010, 19:51:16
0

В Rails 4.1 добавлены Hash # compact и Hash # compact! в качестве основного расширения для Ruby's Hash класс. Вы можете использовать их так:

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: эта реализация не является рекурсивной. Любопытно, что они реализовали это, используя #select вместо #delete_if по соображениям производительности. См. здесь для ознакомления с критерием .

Если вы хотите перенести его в приложение Rails 3:

# 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
ответил dgilperez 23 PM00000080000000931 2014, 20:09:09
0

Этот тоже удалит пустые хэши:

swoop = Proc.new { |k, v| v.delete_if(&swoop) if v.kind_of?(Hash);  v.empty? }
hsh.delete_if &swoop
ответил punund 28 FebruaryEurope/MoscowbTue, 28 Feb 2012 16:36:19 +0400000000pmTue, 28 Feb 2012 16:36:19 +040012 2012, 16:36:19
0

Я знаю, что этот поток немного староват, но я нашел лучшее решение, которое поддерживает многомерные хеши. Он использует delete_if? кроме его многомерного и очищает все с пустым значением по умолчанию, и если блок передается, он передается через его потомков.

# 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
ответил Kelly Becker 11 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowTue, 11 Sep 2012 02:10:11 +0400 2012, 02:10:11
0

Вы можете использовать Hash # reject удалить пустые пары ключ /значение из рубинового хэша.

# Remove empty strings
{ a: 'first', b: '', c: 'third' }.reject { |key,value| value.empty? } 
#=> {:a=>"first", :c=>"third"}

# Remove nil
{a: 'first', b: nil, c: 'third'}.reject { |k,v| v.nil? } 
# => {:a=>"first", :c=>"third"}

# Remove nil & empty strings
{a: '', b: nil, c: 'third'}.reject { |k,v| v.nil? || v.empty? } 
# => {:c=>"third"}
ответил dashvvv 17 FebruaryEurope/MoscowbWed, 17 Feb 2016 11:15:17 +0300000000amWed, 17 Feb 2016 11:15:17 +030016 2016, 11:15:17
0

Я создал для этого метод deep_compact, который рекурсивно отфильтровывает ноль записей (и, необязательно, пустые записи):

class Hash
  # Recursively filters out nil (or blank - e.g. "" if exclude_blank: true is passed as an option) records from a Hash
  def deep_compact(options = {})
    inject({}) do |new_hash, (k,v)|
      result = options[:exclude_blank] ? v.blank? : v.nil?
      if !result
        new_value = v.is_a?(Hash) ? v.deep_compact(options).presence : v
        new_hash[k] = new_value if new_value
      end
      new_hash
    end
  end
end
ответил mwalsher 7 AMpTue, 07 Apr 2015 00:28:49 +030028Tuesday 2015, 00:28:49
0

В Simple один вкладыш для удаления нулевых значений в Hash

rec_hash.each {|key,value| rec_hash.delete(key) if value.blank? } 
ответил ramya 29 +03002014-10-29T11:26:48+03:00312014bEurope/MoscowWed, 29 Oct 2014 11:26:48 +0300 2014, 11:26:48

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132