আমার একটি হ্যাশ রয়েছে:
h1 = {:a => :A, :b => :B, :c => :C, :d => :D}
এর মতো সাব-হ্যাশ উত্তোলনের সর্বোত্তম উপায় কী?
h1.extract_subhash(:b, :d, :e, :f) # => {:b => :B, :d => :D}
h1 #=> {:a => :A, :c => :C}
আমার একটি হ্যাশ রয়েছে:
h1 = {:a => :A, :b => :B, :c => :C, :d => :D}
এর মতো সাব-হ্যাশ উত্তোলনের সর্বোত্তম উপায় কী?
h1.extract_subhash(:b, :d, :e, :f) # => {:b => :B, :d => :D}
h1 #=> {:a => :A, :c => :C}
উত্তর:
আপনি যদি বিশেষত পদ্ধতিটি নিষ্কাশিত উপাদানগুলি ফেরত করতে চান তবে এইচ 1 একই থাকে:
h1 = {:a => :A, :b => :B, :c => :C, :d => :D}
h2 = h1.select {|key, value| [:b, :d, :e, :f].include?(key) } # => {:b=>:B, :d=>:D}
h1 = Hash[h1.to_a - h2.to_a] # => {:a=>:A, :c=>:C}
এবং আপনি যদি এটি হ্যাশ শ্রেণিতে প্যাচ করতে চান:
class Hash
def extract_subhash(*extract)
h2 = self.select{|key, value| extract.include?(key) }
self.delete_if {|key, value| extract.include?(key) }
h2
end
end
আপনি যদি কেবল হ্যাশ থেকে নির্দিষ্ট উপাদানগুলি সরাতে চান, এটি মুছুন_আইফ ব্যবহার করে অনেক সহজ ।
h1 = {:a => :A, :b => :B, :c => :C, :d => :D}
h1.delete_if {|key, value| [:b, :d, :e, :f].include?(key) } # => {:a=>:A, :c=>:C}
h1 # => {:a=>:A, :c=>:C}
slice
বা except
আপনার প্রয়োজনের উপর নির্ভর করে) আরও পরিষ্কার
ActiveSupport
, 2.3.8 থেকে অন্তত চারটি সুবিধাজনক পদ্ধতি প্রদান করে: #slice
, #except
এবং তাদের ধ্বংসাত্মক প্রতিরূপ: #slice!
এবং #except!
। এগুলি অন্য উত্তরে উল্লেখ করা হয়েছিল, তবে তাদের এক জায়গায় যোগ করতে:
x = {a: 1, b: 2, c: 3, d: 4}
# => {:a=>1, :b=>2, :c=>3, :d=>4}
x.slice(:a, :b)
# => {:a=>1, :b=>2}
x
# => {:a=>1, :b=>2, :c=>3, :d=>4}
x.except(:a, :b)
# => {:c=>3, :d=>4}
x
# => {:a=>1, :b=>2, :c=>3, :d=>4}
ঠ্যাং পদ্ধতিগুলির রিটার্ন মানগুলি নোট করুন। তারা কেবল বিদ্যমান হ্যাশকেই উপযুক্ত করবে না তবে মুছে ফেলা (রাখা নয়) এন্ট্রিও ফিরিয়ে দেবে। Hash#except!
মামলা সেরা উদাহরণ প্রশ্নে দেওয়া:
x = {a: 1, b: 2, c: 3, d: 4}
# => {:a=>1, :b=>2, :c=>3, :d=>4}
x.except!(:c, :d)
# => {:a=>1, :b=>2}
x
# => {:a=>1, :b=>2}
ActiveSupport
পুরো রেলগুলির প্রয়োজন হয় না, এটি বেশ হালকা ওজনের। প্রকৃতপক্ষে, প্রচুর নন-রেল রত্নগুলি এর উপর নির্ভর করে, তাই সম্ভবত আপনার এটি ইতিমধ্যে জেমফিল.লকে রয়েছে। নিজের থেকে হ্যাশ ক্লাস বাড়ানোর দরকার নেই।
x.except!(:c, :d)
(ঠুং সঙ্গে) হওয়া উচিত # => {:a=>1, :b=>2}
। আপনার উত্তরটি সম্পাদনা করতে পারলে ভাল।
আপনি পাগল ব্যবহার করেন তাহলে , হ্যাশ # ফালি যেতে উপায়।
{:a => :A, :b => :B, :c => :C, :d => :D}.slice(:a, :c)
# => {:a => :A, :c => :C}
আপনি পাগল ব্যবহার না করা হলে , হ্যাশ # values_at একই আদেশ মান ফিরে আসবে যেমন আপনি তাদেরকে জিজ্ঞেস করেন , যাতে আপনি এটা করতে পারেন:
def slice(hash, *keys)
Hash[ [keys, hash.values_at(*keys)].transpose]
end
def except(hash, *keys)
desired_keys = hash.keys - keys
Hash[ [desired_keys, hash.values_at(*desired_keys)].transpose]
end
প্রাক্তন:
slice({foo: 'bar', 'bar' => 'foo', 2 => 'two'}, 'bar', 2)
# => {'bar' => 'foo', 2 => 'two'}
except({foo: 'bar', 'bar' => 'foo', 2 => 'two'}, 'bar', 2)
# => {:foo => 'bar'}
ব্যাখ্যা:
আউট এর {:a => 1, :b => 2, :c => 3}
আমরা চাই{:a => 1, :b => 2}
hash = {:a => 1, :b => 2, :c => 3}
keys = [:a, :b]
values = hash.values_at(*keys) #=> [1, 2]
transposed_matrix =[keys, values].transpose #=> [[:a, 1], [:b, 2]]
Hash[transposed_matrix] #=> {:a => 1, :b => 2}
আপনি যদি মনে করেন যে বানরের প্যাচিংটি হ'ল উপায়, আপনি যা চান তা নিম্নলিখিত:
module MyExtension
module Hash
def slice(*keys)
::Hash[[keys, self.values_at(*keys)].transpose]
end
def except(*keys)
desired_keys = self.keys - keys
::Hash[[desired_keys, self.values_at(*desired_keys)].transpose]
end
end
end
Hash.include MyExtension::Hash
রুবি 2.5 যোগ করেছেন হ্যাশ # টুকরা :
h = { a: 100, b: 200, c: 300 }
h.slice(:a) #=> {:a=>100}
h.slice(:b, :c, :d) #=> {:b=>200, :c=>300}
আপনি স্লাইস! (* কী) ব্যবহার করতে পারেন যা অ্যাক্টিভসপোর্টের মূল এক্সটেনশনে উপলব্ধ
initial_hash = {:a => 1, :b => 2, :c => 3, :d => 4}
extracted_slice = initial_hash.slice!(:a, :c)
প্রাথমিক_হ্যাশ এখন হবে
{:b => 2, :d =>4}
প্রত্যাহার_স্লাইড হবে এখন
{:a => 1, :c =>3}
আপনি দেখতে পারেন slice.rb in ActiveSupport 3.1.3
module HashExtensions
def subhash(*keys)
keys = keys.select { |k| key?(k) }
Hash[keys.zip(values_at(*keys))]
end
end
Hash.send(:include, HashExtensions)
{:a => :A, :b => :B, :c => :C, :d => :D}.subhash(:a) # => {:a => :A}
def subhash(*keys) select {|k,v| keys.include?(k)} end
h1 = {:a => :A, :b => :B, :c => :C, :d => :D}
keys = [:b, :d, :e, :f]
h2 = (h1.keys & keys).each_with_object({}) { |k,h| h.update(k=>h1.delete(k)) }
#=> {:b => :B, :d => :D}
h1
#=> {:a => :A, :c => :C}
class Hash
def extract(*keys)
key_index = Hash[keys.map{ |k| [k, true] }] # depends on the size of keys
partition{ |k, v| key_index.has_key?(k) }.map{ |group| Hash[group] }
end
end
h1 = {:a => :A, :b => :B, :c => :C, :d => :D}
h2, h1 = h1.extract(:b, :d, :e, :f)
প্রস্তাবিত পদ্ধতির সাথে এখানে দ্রুত পারফরম্যান্স তুলনা #select
করা দ্রুততম বলে মনে হচ্ছে
k = 1_000_000
Benchmark.bmbm do |x|
x.report('select') { k.times { {a: 1, b: 2, c: 3}.select { |k, _v| [:a, :b].include?(k) } } }
x.report('hash transpose') { k.times { Hash[ [[:a, :b], {a: 1, b: 2, c: 3}.fetch_values(:a, :b)].transpose ] } }
x.report('slice') { k.times { {a: 1, b: 2, c: 3}.slice(:a, :b) } }
end
Rehearsal --------------------------------------------------
select 1.640000 0.010000 1.650000 ( 1.651426)
hash transpose 1.720000 0.010000 1.730000 ( 1.729950)
slice 1.740000 0.010000 1.750000 ( 1.748204)
----------------------------------------- total: 5.130000sec
user system total real
select 1.670000 0.010000 1.680000 ( 1.683415)
hash transpose 1.680000 0.010000 1.690000 ( 1.688110)
slice 1.800000 0.010000 1.810000 ( 1.816215)
পরিমার্জনটি এর মতো দেখাবে:
module CoreExtensions
module Extractable
refine Hash do
def extract(*keys)
select { |k, _v| keys.include?(k) }
end
end
end
end
এবং এটি ব্যবহার করতে:
using ::CoreExtensions::Extractable
{ a: 1, b: 2, c: 3 }.extract(:a, :b)
উভয় delete_if
এবং keep_if
রুবি কোর অংশ। এই Hash
ধরণের প্যাচ না করে আপনি যা চান তা এখানে অর্জন করতে পারেন ।
h1 = {:a => :A, :b => :B, :c => :C, :d => :D}
h2 = h1.clone
p h1.keep_if { |key| [:b, :d, :e, :f].include?(key) } # => {:b => :B, :d => :D}
p h2.delete_if { |key, value| [:b, :d, :e, :f].include?(key) } #=> {:a => :A, :c => :C}
আরও তথ্যের জন্য ডকুমেন্টেশন থেকে নীচের লিঙ্কগুলি দেখুন:
অন্যরা যেমন উল্লেখ করেছে, রুবি 2.5 হ্যাশ # স্লাইস পদ্ধতি যুক্ত করেছে।
রেল 5.2.0 বেটা 1 এছাড়াও রুবির পূর্ববর্তী সংস্করণ ব্যবহার করছে এমন কাঠামোর ব্যবহারকারীদের কার্যকারিতা ঝিমিয়ে দেওয়ার জন্য এটি হ্যাশ # স্লাইসের নিজস্ব সংস্করণ যুক্ত করেছে। https://github.com/rails/rails/commit/01ae39660243bc5f0a986e20f9c9bff312b1b5f8
যদি কোনও কারণে আপনার নিজের বাস্তবায়নের সন্ধান করে তবে এটি একটি দুর্দান্ত একটি লাইনারও রয়েছে:
def slice(*keys)
keys.each_with_object(Hash.new) { |k, hash| hash[k] = self[k] if has_key?(k) }
end unless method_defined?(:slice)
এই কোডটি আপনি যে কার্যকারিতাটি হ্যাশ শ্রেণিতে জিজ্ঞাসা করছেন তা ইনজেকশন দেয়:
class Hash
def extract_subhash! *keys
to_keep = self.keys.to_a - keys
to_delete = Hash[self.select{|k,v| !to_keep.include? k}]
self.delete_if {|k,v| !to_keep.include? k}
to_delete
end
end
এবং আপনি সরবরাহিত ফলাফল উত্পাদন করে:
h1 = {:a => :A, :b => :B, :c => :C, :d => :D}
p h1.extract_subhash!(:b, :d, :e, :f) # => {b => :B, :d => :D}
p h1 #=> {:a => :A, :c => :C}
দ্রষ্টব্য: এই পদ্ধতিটি আসলে উত্তোলিত কীগুলি / মানগুলি প্রদান করে।
এখানে একটি কার্যকর সমাধান রয়েছে যা আপনি যদি রুবি 2.5 তে চালাচ্ছেন না এবং আপনি যদি নতুন পদ্ধতি যুক্ত করে আপনার হ্যাশ শ্রেণিকে কলুষিত করতে চান না তবে সেই ক্ষেত্রে কার্যকর হতে পারে:
slice_hash = -> keys, hash { hash.select { |k, _v| keys.include?(k) } }.curry
তারপরে আপনি এটিকে নেস্টেড হ্যাশগুলিতেও প্রয়োগ করতে পারেন:
my_hash = [{name: "Joe", age: 34}, {name: "Amy", age: 55}]
my_hash.map(&slice_hash.([:name]))
# => [{:name=>"Joe"}, {:name=>"Amy"}]
স্লাইস পদ্ধতিতে কেবল একটি সংযোজন, আপনি যদি মূল হ্যাশ থেকে পৃথক করতে চান এমন সুভাষ কীগুলি আপনার পছন্দ মতো করতে পারেন,
slice(*dynamic_keys) # dynamic_keys should be an array type
আমরা কীগুলি লুপ করে এটি করতে পারি কেবলমাত্র আমরা এক্সট্র্যাক্ট করতে চাই এবং কীটি উপস্থিত রয়েছে তা যাচাই করে তারপরে এটি নিষ্কাশন করতে পারি।
class Hash
def extract(*keys)
extracted_hash = {}
keys.each{|key| extracted_hash[key] = self.delete(key) if self.has_key?(key)}
extracted_hash
end
end
h1 = {:a => :A, :b => :B, :c => :C, :d => :D}
h2 = h1.extract(:b, :d, :e, :f)