হ্যাশ / ওয়াইএএমএল থেকে সমস্ত খালি উপাদানগুলি সরিয়ে ফেলা হচ্ছে?


উত্তর:


70

আপনি এটির মতো হ্যাশে একটি কমপ্যাক্ট পদ্ধতি যুক্ত করতে পারেন

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

2
কমপ্যাক্ট কেবল নীল অপসারণ করা উচিত। মিথ্যা মানগুলি নয়
ইসমাইল

1
এটিতে একটি সমস্যা রয়েছে: Hash#delete_ifএটি একটি ধ্বংসাত্মক অপারেশন, যখন compactপদ্ধতিগুলি অবজেক্টটিকে সংশোধন করে না। আপনি ব্যবহার করতে পারেন Hash#reject। অথবা পদ্ধতিটি কল করুন Hash#compact!
টোকল্যান্ড

5
দয়া করে মনে রাখবেন compactএবং compact!রুবি => 2.4.0 আদর্শ আসা, এবং পাগল => 4.1। তারা যদিও পুনরাবৃত্ত হয়।
এইডান

রিকার্সিভ সংস্করণ নেই সঙ্গে কাজ HashWithIndifferentAccess.. আমার সংস্করণ পরীক্ষা করুন stackoverflow.com/a/53958201/1519240
user1519240

157

৪.১ টি পাখি যোগ করেছে হ্যাশ # কমপ্যাক্ট এবং হ্যাশ # কমপ্যাক্ট! রুবির 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                  
# => {}

শিরোনাম: এই প্রয়োগটি পুনরাবৃত্ত হয় না। একটা কৌতুহল আসতেই, তারা এটা ব্যবহার করে বাস্তবায়ন করা #selectপরিবর্তে #delete_ifকর্মক্ষমতা কারণে। মানদণ্ডের জন্য এখানে দেখুন ।

আপনি যদি এটি আপনার রেল 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

3
সুন্দর এবং পরিপাটি, তবে সম্ভবত এটি লক্ষণীয় যে গ্রহণযোগ্য উত্তরগুলির বিপরীতে রেলের এক্সটেনশনটি পুনরাবৃত্তি নয়?
স্যাররোলিনস

2
এটি খালি হ্যাশ বাদ দেয়।
সেবাস্তিয়ান পালমা

142

Hsh.delete_if ব্যবহার করুন । আপনার নির্দিষ্ট ক্ষেত্রে, এর মতো কিছু:hsh.delete_if { |k, v| v.empty? }


6
পুনরাবৃত্তিযোগ্য একটি:proc = Proc.new { |k, v| v.kind_of?(Hash) ? (v.delete_if(&l); nil) : v.empty? }; hsh.delete_if(&proc)
ড্যানিয়েল ও'হারা

3
আমি বিশ্বাস করি আপনার অন্যথায় সঠিক উত্তরটিতে একটি টাইপো রয়েছে: proc = Proc.new {| k, v | v.Point_of? (হাশ)? (v.delete_if (& proc); শূন্য): v.empty? }; hsh.delete_if (& proc)
acw

3
@ তবে মনে হয় তারা শুনেছেন! api.rubyonrails.org/classes/Hash.html#method-i-compact (রেল 4.1)
ডিজিলেপ্রেজ

2
এটি শূন্য NoMethodErrorহলে একটি নিক্ষেপ করবে v
জেরোড

6
আপনি .delete_if {| k, v | ব্যবহার করতে পারেন v.blank? }
সেরিহি নাদোলিনস্কিই

8

আপনি যদি রুবি ২.৪+ ব্যবহার করেন, আপনি কল করতে পারেন compactএবংcompact!

h = { a: 1, b: false, c: nil }
h.compact! #=> { a: 1, b: false }

https://ruby-doc.org/core-2.4.0/Hash.html#method-i-compact-21


1
আমিও দরকারী খুঁজে পেয়েছি হ্যাশ.এসসিপ্ট (: কী) পদ্ধতিটি
ফায়ারড্রেগন

7

এটি খালি হ্যাশগুলিও মুছবে:

swoop = Proc.new { |k, v| v.delete_if(&swoop) if v.kind_of?(Hash);  v.empty? }
hsh.delete_if &swoop

1
রেল সংস্করণ, এটি অ্যারে, হ্যাশ বা স্ট্রিং (ফিক্সনামের মতো) এর চেয়ে অন্য ধরণের মানগুলির সাথেও কাজ করে:swoop = Proc.new { |k, v| v.delete_if(&swoop) if v.kind_of?(Hash); v.blank? }
wdspkr

6

আপনি রুবি হ্যাশ থেকে খালি কী / মান জোড়া সরাতে হ্যাশ # প্রত্যাখ্যান ব্যবহার করতে পারেন ।

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

4
অবগতির জন্য: .empty?তাই আপনি ব্যবহার করতে পারেন সংখ্যার জন্য ত্রুটি ছোঁড়া, .blank?Rails
বাজিকর

5

উভয় hashes এবং অ্যারে জন্য কাজ করে

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

কারও উত্তর উপর ভিত্তি করে PS, ক্যান্ট খুঁজে

ব্যবহার - Helpers::RecursiveCompact.recursive_compact(something)


4

আমি জানি এই থ্রেডটি কিছুটা পুরানো তবে আমি আরও ভাল সমাধান নিয়ে এসেছি যা বহুমাত্রিক হ্যাশগুলিকে সমর্থন করে। এটি মুছে ফেলা_আইফ ব্যবহার করে? এর বহুমাত্রিক ব্যতীত এবং ডিফল্টরূপে খালি মান সহ কোনও কিছুই পরিষ্কার করে দেয় এবং যদি কোনও ব্লক পাস হয়ে যায় তবে এটি শিশুদের মধ্য দিয়ে চলে যায়।

# 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

4

আমি এর জন্য একটি গভীর_কম্প্যাক্ট পদ্ধতি তৈরি করেছি যা পুনরাবৃত্তভাবে শূন্য রেকর্ডগুলি ফিল্টার করে (এবং optionচ্ছিকভাবে, ফাঁকা রেকর্ডগুলিও):

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

4

রুবি Hash#compact, Hash#compact!এবং Hash#delete_if!নেস্টেড nil, empty?এবং / অথবা blank?মানগুলিতে কাজ করে না । মনে রাখবেন যে, আধুনিক দুটি পদ্ধতি ধ্বংসাত্মক হয়, এবং যে সব nil, "", false, []এবং {}মান হিসাবে গণনা করা হয় blank?

Hash#compactএবং Hash#compact!কেবলমাত্র কারাগারে, বা রুবি সংস্করণে ২.৪.০ এবং তারপরে উপলব্ধ।

এখানে একটি অ-ধ্বংসাত্মক সমাধান যা nilসমস্ত falseমান রাখার সাথে সাথে সমস্ত খালি অ্যারে, হ্যাশ, স্ট্রিং এবং মানগুলি সরিয়ে দেয় :

( blank?সাথে nil?বা empty?প্রয়োজনের সাথে প্রতিস্থাপন করা যেতে পারে ))

def remove_blank_values(hash)
  hash.each_with_object({}) do |(k, v), new_hash|
    unless v.blank? && v != false
      v.is_a?(Hash) ? new_hash[k] = remove_blank_values(v) : new_hash[k] = v
    end
  end
end

একটি ধ্বংসাত্মক সংস্করণ:

def remove_blank_values!(hash)
  hash.each do |k, v|
    if v.blank? && v != false
      hash.delete(k)
    elsif v.is_a?(Hash)
      hash[k] = remove_blank_values!(v)
    end
  end
end

বা, আপনি যদি Hashক্লাসে উদাহরণ পদ্ধতি হিসাবে উভয় সংস্করণ যুক্ত করতে চান :

class Hash
  def remove_blank_values
    self.each_with_object({}) do |(k, v), new_hash|
      unless v.blank? && v != false
        v.is_a?(Hash) ? new_hash[k] = v.remove_blank_values : new_hash[k] = v
      end
    end
  end

  def remove_blank_values!
    self.each_pair do |k, v|
      if v.blank? && v != false
        self.delete(k)
      elsif v.is_a?(Hash)
        v.remove_blank_values!
      end
    end
  end
end

অন্যান্য অপশন:

  • খালি স্ট্রিংগুলি কঠোরভাবে সরিয়ে ফেলতে এর v.blank? && v != falseসাথে প্রতিস্থাপন করুনv.nil? || v == ""nil মানগুলি
  • প্রতিস্থাপন v.blank? && v != falseসঙ্গে v.nil?কঠোরভাবে মুছে ফেলার জন্য nilমান
  • প্রভৃতি

falseমানগুলি রাখতে এবং অন্যান্য বিকল্পগুলি উপস্থাপন করতে 2017/03/15 সম্পাদনা করুন


3

আমাদের সংস্করণ: এটি খালি স্ট্রিং এবং শূন্য মানগুলিও পরিষ্কার করে

class Hash

  def compact
    delete_if{|k, v|

      (v.is_a?(Hash) and v.respond_to?('empty?') and v.compact.empty?) or
          (v.nil?)  or
          (v.is_a?(String) and v.empty?)
    }
  end

end

3

হ্যাশে নাল মানগুলি মুছে ফেলার জন্য সাধারণ একটি লাইনারে,

rec_hash.each {|key,value| rec_hash.delete(key) if value.blank? } 

সাবধান, blank?খালি স্ট্রিংয়ের জন্যও যায়
হার্টজেল গিনেস

2

এর মতো ফেসবুক লাইব্রেরি (স্ট্যান্ডার্ড লাইব্রেরি থেকে একটি অনুপস্থিত বৈশিষ্ট্য) দিয়ে করা যেতে পারে :

require 'hash/compact'
require 'enumerable/recursively'
hash.recursively { |v| v.compact! }

যে কোনও গণ্যকারীর সাথে কাজ করে (অ্যারে, হ্যাশ সহ)।

দেখ, আমি কেমন যাও recursively পদ্ধতি বাস্তবায়িত হয়।


0

আমি বিশ্বাস করি একটি স্ব পুনরাবৃত্তি পদ্ধতি ব্যবহার করা ভাল। যেভাবে এটি প্রয়োজন হিসাবে গভীর হয়। মানটি যদি শূন্য হয় বা খালি হ্যাশ হয় তবে এটি মূল মান জুটি মুছে ফেলবে।

class Hash
  def compact
    delete_if {|k,v| v.is_a?(Hash) ? v.compact.empty? : v.nil? }
  end
end

তারপরে এটি ব্যবহার করা এর মতো দেখতে পাবেন:

x = {:a=>{:b=>2, :c=>3}, :d=>nil, :e=>{:f=>nil}, :g=>{}}
# => {:a=>{:b=>2, :c=>3}, :d=>nil, :e=>{:f=>nil}, :g=>{}} 
x.compact
# => {:a=>{:b=>2, :c=>3}}

খালি হ্যাশগুলি রাখতে আপনি এটিকে সহজ করতে পারেন।

class Hash
  def compact
    delete_if {|k,v| v.compact if v.is_a?(Hash); v.nil? }
  end
end

হুম। বিজ্ঞপ্তি সংক্রান্ত রেফারেন্সগুলি অসীম লুপ IIUC এ নিয়ে যেতে পারে।
হার্টজেল গিনেস 21

0
class Hash   
  def compact
    def _empty?(val)
      case val
      when Hash     then val.compact.empty?
      when Array    then val.all? { |v| _empty?(v) }
      when String   then val.empty?
      when NilClass then true
      # ... custom checking 
      end
    end

    delete_if { |_key, val| _empty?(val) }   
  end 
end

নোট করুন যে "যখন হ্যাশ তখন কমপ্যাক্ট (ভাল) .Empty?" "যখন হ্যাশ তখন Val.compact.empty হবে?"
আলেক্সিটিসি


0

Https://stackoverflow.com/a/14773555/1519240 এর পুনরাবৃত্ত সংস্করণ কাজ করে, তবে এমন HashWithIndifferentAccessবা অন্যান্য শ্রেণীর সাথে নয় যা হ্যাশ জাতীয় ধরণের ..

আমি যে সংস্করণটি ব্যবহার করছি তা এখানে:

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) হ্যাশের মতো আরও ক্লাস গ্রহণ করবে।

আপনি চিহ্ন এবং স্ট্রিং উভয়ই ব্যবহার করে নতুন হ্যাশ অ্যাক্সেস করতে চাইলে আপনি এটি inject({})দ্বারা প্রতিস্থাপন inject(HashWithIndifferentAccess.new)করতে পারেন।


0

এখানে আমার কিছু রয়েছে:

# recursively remove empty keys (hashes), values (array), hashes and arrays from hash or array
def sanitize data
  case data
  when Array
    data.delete_if { |value| res = sanitize(value); res.blank? }
  when Hash
    data.delete_if { |_, value| res = sanitize(value); res.blank? }
  end
  data.blank? ? nil : data
end

0

একটি হ্যাশ থেকে গভীর মুছে ফেলা শূন্য।

  # 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

আপনি যদি সংস্করণ থেকে শুরু করে Rails(বা স্ট্যান্ডেলোন ActiveSupport) ব্যবহার করেন 6.1, এমন একটি compact_blankপদ্ধতি রয়েছে যা blankহ্যাশগুলি থেকে মানগুলি সরিয়ে দেয় ।

এটি Object#blank?কোনও আইটেম ফাঁকা কিনা তা নির্ধারণের জন্য হুডের নীচে ব্যবহার করে ।

{ a: "", b: 1, c: nil, d: [], e: false, f: true }.compact_blank
# => { b: 1, f: true }

এখানে ডক্সের একটি লিঙ্ক এবং আপেক্ষিক PR এর লিঙ্ক

একটি ধ্বংসাত্মক রূপটি উপলব্ধ is দেখুন Hash#compact_blank!


আপনার যদি প্রয়োজন তবেই সরান nil মানগুলি ,

দয়া করে, রুবি বিল্ড-ইন Hash#compactএবং Hash#compact!পদ্ধতিগুলি বিবেচনা করুন।

{ a: 1, b: false, c: nil }.compact
# => { a: 1, b: false }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.