কীভাবে হ্যাশ থেকে একটি কী সরান এবং বাকি রুশ / রেলগুলিতে পাবেন?


560

হ্যাশ আমি একটি নতুন জুড়ি যোগ করতে:

{: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 })

এক লাইনে


1
আপনি যদি সত্যই এটির প্রয়োজন হয় তবে এই কাস্টম পদ্ধতিটি যুক্ত করতে আপনি হ্যাশ-এ বিল্টটি সর্বদা প্রসারিত করতে পারেন (রানটাইমের সময় খুলুন)।
dbryson

উত্তর:


750

কারাগারে একটি ছাড়া / বাদে আছে! এমন কীগুলি সরানো হলে হ্যাশটি ফেরত দেওয়ার পদ্ধতি । আপনি যদি ইতিমধ্যে রেলগুলি ব্যবহার করেন তবে এটির নিজস্ব সংস্করণ তৈরি করার কোনও ধারণা নেই।

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

51
আপনাকে পুরো রেল স্ট্যাক ব্যবহার করতে হবে না। আপনি যে কোনও রুবি অ্যাপ্লিকেশনটিতে অ্যাক্টিভসপোর্ট অন্তর্ভুক্ত করতে পারেন।
ফ্রাই

10
ফ্রাইয়ের উত্তরে যুক্ত করতে, আপনাকে এমনকি সমস্ত অ্যাক্টিভাসপোর্ট লোড করার প্রয়োজন নেই; আপনি কেবল তখনই তাদের অন্তর্ভুক্ত করতে পারেনrequire "active_support/core_ext/hash/except"
জিএমএ

সম্পাদনা করতে খুব দেরী: আমার অর্থ ছিল "রত্নকে অন্তর্ভুক্ত করুন" তাদের "অন্তর্ভুক্ত নয়"
জিএমএ

@ জিএমএ: যখন আপনার পাঁচ মিনিটের সম্পাদনা শেষ হয়, আপনি সর্বদা একটি মন্তব্য অনুলিপি, মুছতে, সংশোধন করতে এবং পোস্ট করতে পারেন।
আইকনোক্লাস্ট

211

অনলাইনার প্লেইন রুবি, এটি কেবল রুবি> 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} 

আলতো চাপার পদ্ধতিটি সর্বদা প্রত্যাশিত বস্তুটি ফেরত দেয় ...

অন্যথায় আপনার যদি প্রয়োজন হয় 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!এবং কীগুলির জন্য রাখে 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} 

18
+1 এটি উল্লেখযোগ্য যে এই পদ্ধতিটি ধ্বংসাত্মক hHash#exceptআসল হ্যাশ পরিবর্তন করবে না।
আপনাকে ধন্যবাদ

3
h.dup.tap { |hs| hs.delete(:a) }আসল হ্যাশটি সংশোধন করা এড়াতে ব্যবহার করুন ।
ম্যাজিকোড

181

কেন শুধু ব্যবহার করবেন না:

hash.delete(key)

2
@ ডিব্রাইসন: আমি একমত যে কখনও কখনও এটির পক্ষে লাভ হয় না। আমি শুধু ভাবছি কেন আছে merge, merge!, delete, কিন্তু কোন detele!...
মিশা Moroshko

1
যদি আপনার সত্যিই এটি ওয়ান লাইনারের মতো প্রয়োজন হয়:foo(hash.delete(key) || hash)
বার্ট গোথালস

13
এটা তোলে রুবি নিয়মাবলী সঙ্গে আরো সামঞ্জস্যপূর্ণ যদি হবে deleteনা না তার পরামিতি পরিবর্তন করুন এবং যদি delete!অস্তিত্ব এবং তার পরামিতি পরিবর্তন করেনি।
ডেভিড জে।

60
এটি প্রশ্নের মধ্যে উল্লিখিত বাকী হ্যাশ ফিরিয়ে দেয় না, এটি মুছে ফেলা কীটির সাথে সম্পর্কিত মানটি ফিরিয়ে দেবে।
এমএইচডি সিরওয়ান

1
মুছুন কীটি ফেরত দেয় তবে এটি হ্যাশকেও পরিবর্তন করে। কেন কোনও মুছে ফেলা হচ্ছে না !, আমার ধারণা হ'ল এটি শব্দার্থগতভাবে কোনও কিছুর উপর মুছে ফেলার কল করা এবং আসলে এটি মুছে ফেলার নয় তা বোঝা যায় না। হ্যাশ.ডিলেট () এর বিপরীতে হ্যাশ.ডিলেট () কে কল করা কোনও বিকল্প নেই।
ডিম পোড়া

85

রুশটিতে একটি হ্যাশ থেকে কীটি সরানোর এবং বাকি হ্যাশ পাওয়ার অনেকগুলি উপায় রয়েছে।

  1. .slice=> এটি নির্বাচিত কীগুলি ফিরিয়ে দেবে এবং আসল হ্যাশ থেকে এগুলি মুছবে না। ব্যবহার করুন slice!আপনি কি স্থায়ীভাবে আর ব্যবহার সহজ অপসারণ করতে চান তাহলে slice

    2.2.2 :074 > hash = {"one"=>1, "two"=>2, "three"=>3}
     => {"one"=>1, "two"=>2, "three"=>3} 
    2.2.2 :075 > hash.slice("one","two")
     => {"one"=>1, "two"=>2} 
    2.2.2 :076 > hash
     => {"one"=>1, "two"=>2, "three"=>3} 
  2. .delete => এটি আসল হ্যাশ থেকে নির্বাচিত কীগুলি মুছে ফেলবে (এটি কেবল একটি চাবি গ্রহণ করতে পারে এবং একের বেশি নয়)।

    2.2.2 :094 > hash = {"one"=>1, "two"=>2, "three"=>3}
     => {"one"=>1, "two"=>2, "three"=>3} 
    2.2.2 :095 > hash.delete("one")
     => 1 
    2.2.2 :096 > hash
     => {"two"=>2, "three"=>3} 
  3. .except=> এটি অবশিষ্ট কীগুলি ফিরিয়ে দেবে তবে আসল হ্যাশ থেকে কোনও কিছুই মুছবে না। ব্যবহার করুন except!আপনি কি স্থায়ীভাবে আর ব্যবহার সহজ অপসারণ করতে চান তাহলে except

    2.2.2 :097 > hash = {"one"=>1, "two"=>2, "three"=>3}
     => {"one"=>1, "two"=>2, "three"=>3} 
    2.2.2 :098 > hash.except("one","two")
     => {"three"=>3} 
    2.2.2 :099 > hash
     => {"one"=>1, "two"=>2, "three"=>3}         
  4. .delete_if=> সেক্ষেত্রে আপনাকে কোনও মানের ভিত্তিতে একটি কী সরিয়ে ফেলতে হবে। এটি স্পষ্টতই মূল হ্যাশ থেকে ম্যাচিং কীগুলি সরিয়ে ফেলবে।

    2.2.2 :115 > hash = {"one"=>1, "two"=>2, "three"=>3, "one_again"=>1}
     => {"one"=>1, "two"=>2, "three"=>3, "one_again"=>1} 
    2.2.2 :116 > value = 1
     => 1 
    2.2.2 :117 > hash.delete_if { |k,v| v == value }
     => {"two"=>2, "three"=>3} 
    2.2.2 :118 > hash
     => {"two"=>2, "three"=>3} 
  5. .compact=> এটি nilহ্যাশ থেকে সমস্ত মান মুছে ফেলার জন্য ব্যবহৃত হয় । ব্যবহার করুন compact!আপনি সরাতে চান তাহলে nilমান স্থায়ীভাবে আর ব্যবহার সহজ compact

    2.2.2 :119 > hash = {"one"=>1, "two"=>2, "three"=>3, "nothing"=>nil, "no_value"=>nil}
     => {"one"=>1, "two"=>2, "three"=>3, "nothing"=>nil, "no_value"=>nil} 
    2.2.2 :120 > hash.compact
     => {"one"=>1, "two"=>2, "three"=>3}

রুবি ২.২.২ এর উপর ভিত্তি করে ফলাফল।


15
sliceএবং exceptব্যবহার করে যোগ করা হয় ActiveSupport::CoreExtensions::Hash। এগুলি রুবি কোরের অংশ নয়। এগুলি দ্বারা ব্যবহার করা যেতে পারেrequire 'active_support/core_ext/hash'
মাদিস N Octmme

3
যেহেতু রুবি 2.5 Hash#sliceস্ট্যান্ডার্ড লাইব্রেরিতে রয়েছে। রুবি-ডোক.আর.অর্গ.ওকোর ২.২.০ / হ্যাশ এইচটিএমএল# মেমোডি- আই- স্লাইস ইয়ে!
মাদিস নেমমে

38

আপনি যদি খাঁটি রুবি ব্যবহার করতে চান (কোনও রেয়েল নেই), এক্সটেনশন পদ্ধতি তৈরি করতে চান না (সম্ভবত আপনার কেবল এটি এক বা দুটি জায়গায় প্রয়োজন এবং টন পদ্ধতির সাহায্যে নেমস্পেসকে দূষিত করতে চান না) এবং চান না জায়গায় হ্যাশ সম্পাদনা করুন (যেমন, আপনি আমার মতো ক্রিয়ামূলক প্রোগ্রামিংয়ের অনুরাগী), আপনি 'নির্বাচন' করতে পারেন:

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

30
#in lib/core_extensions.rb
class Hash
  #pass single or array of keys, which will be removed, returning the remaining hash
  def remove!(*keys)
    keys.each{|key| self.delete(key) }
    self
  end

  #non-destructive version
  def remove(*keys)
    self.dup.remove!(*keys)
  end
end

#in config/initializers/app_environment.rb (or anywhere in config/initializers)
require 'core_extensions'

আমি এটি সেট আপ করেছি যাতে। সরানোর সময় সরানো চাবিগুলি সহ হ্যাশটির অনুলিপি ফিরে আসে! হ্যাশ নিজেই পরিবর্তন করে। এটি রুবি সম্মেলনের সাথে মিল রেখে keeping যেমন কনসোল থেকে

>> hash = {:a => 1, :b => 2}
=> {:b=>2, :a=>1}
>> hash.remove(:a)
=> {:b=>2}
>> hash
=> {:b=>2, :a=>1}
>> hash.remove!(:a)
=> {:b=>2}
>> hash
=> {:b=>2}
>> hash.remove!(:a, :b)
=> {}

26

আপনি মণি except!থেকে ব্যবহার করতে পারেন facets:

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

আসল হ্যাশ পরিবর্তন হয় না।

সম্পাদনা: রাসেল যেমন বলেছেন, দিকগুলির কিছু লুকানো সমস্যা রয়েছে এবং এটি অ্যাক্টিভসপোর্টের সাথে পুরোপুরি এপিআই-সামঞ্জস্যপূর্ণ নয়। অন্যদিকে অ্যাক্টিভসপোর্টটি দিকগুলির মতো সম্পূর্ণ নয়। শেষ পর্যন্ত, আমি AS ব্যবহার করব এবং আপনার কোডে প্রান্তের কেসগুলি দেই।


কেবল require 'facets/hash/except'এবং এগুলি কোনও "সমস্যা" নয় (এপিআই 100% না হয়ে অন্য যে কোনও সমস্যা হবে তা নিশ্চিত নয়)। আপনি যদি এএস ব্যবহার করে কোনও রেল প্রকল্প করেন তবে তা বোঝা যায়, যদি না হয় তবে এর চেয়ে আরও ছোট পায়ের ছাপ রয়েছে।
ট্রান্স

@ ট্রান্স অ্যাক্টিভসপোর্টের আজকাল খুব ছোট পায়ের ছাপ রয়েছে এবং আপনার এটির কিছু অংশের প্রয়োজন হতে পারে। ঠিক মত দিকগুলি, তবে এতে আরও অনেকগুলি চোখ রয়েছে (সুতরাং আমি মনে করি এটি আরও ভাল পর্যালোচনা পেয়েছে)।
পুনরায়

19

বাঁদর প্যাচিংয়ের পরিবর্তে বা অযথা বড় বড় লাইব্রেরিগুলি অন্তর্ভুক্ত করার পরিবর্তে, আপনি যদি রুবি 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

17

খাঁটি রুবিতে:

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

13

কারাগারে রুবি দেখুন : একাধিক হ্যাশ কী মুছুন

hash.delete_if{ |k,| keys_to_delete.include? k }

key_to_delete.each {| k | hash.delete (k) large বড় ডেটাসেটের জন্য অনেক দ্রুত। ভুল হলে আমাকে সংশোধন করুন
বিগনেশ জায়েভেল

@ বিগনেশজায়াভেল, আপনি ঠিক বলেছেন তবে ওপি চেয়েছিল হ্যাশটি ফিরিয়ে দেওয়া হোক। eachঅ্যারে ফিরিয়ে দিতে হবে।
নাকিলন

3

মুছে ফেলা হলে হ্যাশটির মুছুন জোড়ায় ফেরত দেওয়া দুর্দান্ত। আমি এটি করছি:

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

1

এটি করার জন্য এটি এক লাইনের উপায়, তবে এটি খুব পাঠযোগ্য নয়। পরিবর্তে দুটি লাইন ব্যবহার করার পরামর্শ দিন।

use_remaining_hash_for_something(Proc.new { hash.delete(:key); hash }.call)

1
Hash#exceptএবং Hash#except!ইতিমধ্যে যথেষ্ট উল্লেখ করা হয়েছে। Proc.newসংস্করণ খুব পাঠযোগ্য হিসাবে আপনি উল্লেখ এবং তুলনায় আরো জটিল নয় use_remaining_hash_for_something(begin hash.delete(:key); hash end)। সম্ভবত এই উত্তরটি মুছুন।
মাইকেল কোহল

1
আমার উত্তর সংক্ষিপ্ত করে ইতিমধ্যে যা বলা হয়েছিল তা সরিয়ে ফেলুন। আপনার মন্তব্যের সাথে আমার উত্তর রাখছি কারণ তারা প্রশ্নের উত্তর দেয় এবং ব্যবহারের জন্য ভাল প্রস্তাব দেয়।
the_minated

0

হ্যাশে কী মুছে ফেলার একাধিক উপায় ways আপনি নীচের থেকে যে কোনও পদ্ধতি ব্যবহার করতে পারেন

hash = {a: 1, b: 2, c: 3}
hash.except!(:a) # Will remove *a* and return HASH
hash # Output :- {b: 2, c: 3}

hash = {a: 1, b: 2, c: 3}
hash.delete(:a) # will remove *a* and return 1 if *a* not present than return nil

অনেকগুলি উপায় আছে, আপনি এখানে হ্যাশের রুবি ডকটি দেখতে পারেন ।

ধন্যবাদ


-12

এটিও কাজ করবে: hash[hey] = nil


3
h = {: a => 1,: b => 2,: সি => 3}; ঘন্টা [: একটি] = শূন্য; h.each {| K, বনাম | p k k the এর মতো নয়: h = {: a => 1,: b => 2,: সি => 3}; h.delete (: একটি); h.each {| K, বনাম | k
p

1
হ্যাশ থেকে একটি কী সরিয়ে ফেলা হ্যাশ থেকে একটি কী এর মান সরিয়ে ফেলার মতো নয়। যেহেতু এটি লোককে বিভ্রান্ত করতে পারে, এই উত্তরটি সরিয়ে ফেলা ভাল।
সেবাস্তিয়ান পালমা
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.