ruby on rails - हैश से एक कुंजी कैसे निकालें और रुबी/रेल में शेष हैश प्राप्त करें?




ruby-on-rails ruby-on-rails-3 (8)

हैश में एक नई जोड़ी जोड़ने के लिए मैं करता हूं:

{:a => 1, :b => 2}.merge!({:c => 3})   #=> {:a => 1, :b => 2, :c => 3}

हैश से एक कुंजी हटाने के लिए एक समान तरीका है?

यह काम:

{:a => 1, :b => 2}.reject! { |k| k == :a }   #=> {:b => 2}

लेकिन मुझे ऐसा कुछ करने की उम्मीद है:

{:a => 1, :b => 2}.delete!(:a)   #=> {:b => 2}

यह महत्वपूर्ण है कि वापसी मूल्य शेष हैश होगा, इसलिए मैं इस तरह की चीजें कर सकता हूं:

foo(my_hash.reject! { |k| k == my_key })

एक पंक्ति में


आप except! उपयोग कर सकते हैं except! facets मणि से:

>> require 'facets' # or require 'facets/hash/except'
=> true
>> {:a => 1, :b => 2}.except(:a)
=> {:b=>2}

मूल हैश नहीं बदलता है।

संपादित करें: जैसा कि रसेल कहते हैं, पहलुओं में कुछ छिपे हुए मुद्दे हैं और सक्रिय समर्थन के साथ पूरी तरह एपीआई-संगत नहीं हैं। दूसरी तरफ ActiveSupport पहलुओं के रूप में पूर्ण नहीं है। अंत में, मैं एएस का उपयोग करता हूं और किनारे के मामलों को आपके कोड में देता हूं।


ऑनलाइनर सादे रूबी, यह केवल रूबी के साथ काम करता है> 1.9.x:

1.9.3p0 :002 > h = {:a => 1, :b => 2}
 => {:a=>1, :b=>2} 
1.9.3p0 :003 > h.tap { |hs| hs.delete(:a) }
 => {:b=>2} 

Tap विधि हमेशा उस ऑब्जेक्ट को वापस लौटाती है जिस पर हमला किया जाता है ...

अन्यथा यदि आपके पास active_support/core_ext/hash (जो प्रत्येक रेल एप्लिकेशन में स्वचालित रूप से आवश्यक है) की आवश्यकता है तो आप अपनी आवश्यकताओं के आधार पर निम्न विधियों में से एक का उपयोग कर सकते हैं:

➜  ~  irb
1.9.3p125 :001 > require 'active_support/core_ext/hash' => true 
1.9.3p125 :002 > h = {:a => 1, :b => 2, :c => 3}
 => {:a=>1, :b=>2, :c=>3} 
1.9.3p125 :003 > h.except(:a)
 => {:b=>2, :c=>3} 
1.9.3p125 :004 > h.slice(:a)
 => {:a=>1} 

except एक ब्लैकलिस्ट दृष्टिकोण slice उपयोग करता है, इसलिए यह तर्क के रूप में सूचीबद्ध सभी कुंजियों को हटा देता है, जबकि slice श्वेतसूची दृष्टिकोण slice उपयोग करता है, इसलिए यह उन सभी कुंजियों को हटा देता है जो तर्क के रूप में सूचीबद्ध नहीं हैं। उन तरीकों का बैंग संस्करण भी मौजूद है ( except! और slice! ) जो दिए गए हैंश को संशोधित करता है लेकिन उनके रिटर्न वैल्यू अलग-अलग हैं, दोनों एक हैश लौटते हैं। यह slice! लिए हटाए गए कुंजी का प्रतिनिधित्व करता है slice! और कुंजियों को except! रखा जाता है except! :

1.9.3p125 :011 > {:a => 1, :b => 2, :c => 3}.except!(:a)
 => {:b=>2, :c=>3} 
1.9.3p125 :012 > {:a => 1, :b => 2, :c => 3}.slice!(:a)
 => {:b=>2, :c=>3} 

बड़े पुस्तकालयों सहित बंदर पैचिंग या अनावश्यक रूप से, यदि आप रूबी 2 का उपयोग कर रहे हैं तो आप परिशोधन का उपयोग कर सकते हैं:

module HashExtensions
  refine Hash do
    def except!(*candidates)
      candidates.each { |candidate| delete(candidate) }
      self
    end

    def except(*candidates)
      dup.remove!(candidates)
    end
  end
end

आप इस कार्यक्रम का उपयोग अपने प्रोग्राम के अन्य हिस्सों को प्रभावित किए बिना, या बड़े बाहरी पुस्तकालयों को शामिल करने के बिना कर सकते हैं।

class FabulousCode
  using HashExtensions

  def incredible_stuff
    delightful_hash.except(:not_fabulous_key)
  end
end

यदि आप शुद्ध रूबी (कोई रेल) ​​का उपयोग नहीं करना चाहते हैं, तो विस्तार विधियां नहीं बनाना चाहते हैं (शायद आपको केवल एक या दो स्थानों में इसकी आवश्यकता है और कई तरीकों से नेमस्पेस को प्रदूषित नहीं करना चाहते हैं) और नहीं चाहते हैं जगह में हैश संपादित करें (यानी, आप मेरे जैसे कार्यात्मक प्रोग्रामिंग के प्रशंसक हैं), आप 'चयन' कर सकते हैं:

>> x = {:a => 1, :b => 2, :c => 3}
=> {:a=>1, :b=>2, :c=>3}
>> x.select{|x| x != :a}
=> {:b=>2, :c=>3}
>> x.select{|x| ![:a, :b].include?(x)}
=> {:c=>3}
>> x
=> {:a=>1, :b=>2, :c=>3}

यह भी काम करेगा: hash[hey] = nil


शुद्ध रूबी में:

{:a => 1, :b => 2}.tap{|x| x.delete(:a)}   # => {:b=>2}


रेल को छोड़कर / छोड़कर है! विधि जो हैश को उन चाबियों से हटा देती है। यदि आप पहले से रेल का उपयोग कर रहे हैं, तो इसका अपना संस्करण बनाने में कोई समझ नहीं है।

class Hash
  # Returns a hash that includes everything but the given keys.
  #   hash = { a: true, b: false, c: nil}
  #   hash.except(:c) # => { a: true, b: false}
  #   hash # => { a: true, b: false, c: nil}
  #
  # This is useful for limiting a set of parameters to everything but a few known toggles:
  #   @person.update(params[:person].except(:admin))
  def except(*keys)
    dup.except!(*keys)
  end

  # Replaces the hash without the given keys.
  #   hash = { a: true, b: false, c: nil}
  #   hash.except!(:c) # => { a: true, b: false}
  #   hash # => { a: true, b: false }
  def except!(*keys)
    keys.each { |key| delete(key) }
    self
  end
end




ruby-hash