Ruby Language
हैश
खोज…
परिचय
एक हैश अद्वितीय कुंजियों और उनके मूल्यों का एक शब्दकोश जैसा संग्रह है। साहचर्य सरणियों को भी कहा जाता है, वे Arrays के समान हैं, लेकिन जहां एक सरणी अपने सूचकांक के रूप में पूर्णांक का उपयोग करता है, एक हैश आपको किसी भी ऑब्जेक्ट प्रकार का उपयोग करने की अनुमति देता है। आप इसकी कुंजी का हवाला देकर हैश में एक नई प्रविष्टि प्राप्त या बनाते हैं।
वाक्य - विन्यास
{first_name: "नोएल", second_name: "एडमंड्स"}
{> first_name => "नोएल": दूसरा_name => "एडमंड्स"}
{"पहला नाम" => "नोएल", "दूसरा नाम" => "एडमंड्स"}
{first_key => first_value, second_key => second_value}
टिप्पणियों
हैश तालिका का उपयोग करके मानों को रूबी मानचित्र कुंजियों में हाशियाँ।
किसी भी हैशेबल ऑब्जेक्ट को चाबियों के रूप में इस्तेमाल किया जा सकता है। हालाँकि, यह एक सामान्य Symbol
का उपयोग करने के लिए बहुत सामान्य है क्योंकि कम ऑब्जेक्ट आवंटन के कारण यह कई रूबी संस्करणों में अधिक कुशल है।
{ key1: "foo", key2: "baz" }
हैश बनाना
रूबी में एक हैश एक वस्तु है जो हैश टेबल को लागू करता है, मानों के लिए कुंजियों की मैपिंग करता है। रूबी {}
का उपयोग करते हुए हैश को परिभाषित करने के लिए एक विशिष्ट शाब्दिक वाक्यविन्यास का समर्थन करता है:
my_hash = {} # an empty hash
grades = { 'Mark' => 15, 'Jimmy' => 10, 'Jack' => 10 }
मानक new
विधि का उपयोग करके एक हैश भी बनाया जा सकता है:
my_hash = Hash.new # any empty hash
my_hash = {} # any empty hash
हेज़ में किसी भी प्रकार के मूल्य हो सकते हैं, जिसमें जटिल प्रकार जैसे सरणियाँ, ऑब्जेक्ट और अन्य हैश शामिल हैं:
mapping = { 'Mark' => 15, 'Jimmy' => [3,4], 'Nika' => {'a' => 3, 'b' => 5} }
mapping['Mark'] # => 15
mapping['Jimmy'] # => [3, 4]
mapping['Nika'] # => {"a"=>3, "b"=>5}
कुंजी भी किसी भी प्रकार की हो सकती है, जिसमें जटिल भी शामिल हैं:
mapping = { 'Mark' => 15, 5 => 10, [1, 2] => 9 }
mapping['Mark'] # => 15
mapping[[1, 2]] # => 9
प्रतीक आमतौर पर हैश कुंजी के रूप में उपयोग किए जाते हैं, और रूबी 1.9 ने विशेष रूप से इस प्रक्रिया को छोटा करने के लिए एक नया वाक्यविन्यास पेश किया। निम्नलिखित हैश समतुल्य हैं:
# Valid on all Ruby versions
grades = { :Mark => 15, :Jimmy => 10, :Jack => 10 }
# Valid in Ruby version 1.9+
grades = { Mark: 15, Jimmy: 10, Jack: 10 }
निम्नलिखित हैश (सभी रूबी संस्करणों में मान्य) अलग है , क्योंकि सभी कुंजी तार हैं:
grades = { "Mark" => 15, "Jimmy" => 10, "Jack" => 10 }
जबकि दोनों सिंटैक्स संस्करणों को मिश्रित किया जा सकता है, निम्न को हतोत्साहित किया जाता है।
mapping = { :length => 45, width: 10 }
रूबी 2.2+ के साथ, प्रतीक कुंजियों के साथ हैश बनाने के लिए एक वैकल्पिक वाक्यविन्यास है (सबसे उपयोगी अगर प्रतीक में रिक्त स्थान हैं):
grades = { "Jimmy Choo": 10, :"Jack Sparrow": 10 }
# => { :"Jimmy Choo" => 10, :"Jack Sparrow" => 10}
पहुँच मान
हैश के व्यक्तिगत मूल्यों को []
और []=
विधियों का उपयोग करके पढ़ा और लिखा जाता है:
my_hash = { length: 4, width: 5 }
my_hash[:length] #=> => 4
my_hash[:height] = 9
my_hash #=> {:length => 4, :width => 5, :height => 9 }
डिफ़ॉल्ट रूप से, एक कुंजी को एक्सेस करना जो हैश रिटर्न nil
में नहीं जोड़ा गया है, जिसका अर्थ है कि कुंजी के मूल्य को देखने का प्रयास करना हमेशा सुरक्षित होता है:
my_hash = {}
my_hash[:age] # => nil
Hashes स्ट्रिंग्स में कुंजियाँ भी रख सकते हैं। यदि आप उन्हें सामान्य रूप से एक्सेस करने का प्रयास करते हैं, तो यह सिर्फ एक nil
लौटाएगा, इसके बजाय आप उनकी स्ट्रिंग कुंजियों द्वारा एक्सेस करते हैं:
my_hash = { "name" => "user" }
my_hash[:name] # => nil
my_hash["name"] # => user
स्थितियों में, जहां कुंजी की उम्मीद या अस्तित्व के लिए आवश्यक हैं के लिए, हैश एक है fetch
विधि जब एक चाबी जो मौजूद नहीं है तक पहुँचने जो एक अपवाद बढ़ा देंगे:
my_hash = {}
my_hash.fetch(:age) #=> KeyError: key not found: :age
एक डिफ़ॉल्ट मान को fetch
अपने दूसरे तर्क के रूप में स्वीकार करता है, जिसे यदि कुंजी पहले से सेट नहीं की गई है, तो लौटा दिया जाता है:
my_hash = {}
my_hash.fetch(:age, 45) #=> => 45
fetch
भी एक ब्लॉक जो करता है, तो कुंजी पहले से निर्धारित नहीं किया गया है दिया जाता है स्वीकार कर सकते हैं:
my_hash = {}
my_hash.fetch(:age) { 21 } #=> 21
my_hash.fetch(:age) do |k|
puts "Could not find #{k}"
end
#=> Could not find age
Hashes भी store
विधि को एक उपनाम के रूप में समर्थन करते हैं []=
:
my_hash = {}
my_hash.store(:age, 45)
my_hash #=> { :age => 45 }
आप values
विधि का उपयोग करके हैश के सभी मान भी प्राप्त कर सकते हैं:
my_hash = { length: 4, width: 5 }
my_hash.values #=> [4, 5]
नोट: यह केवल रूबी 2.3+ के लिए है #dig
नेस्टेड Hash
लिए काम करता है। प्रत्येक चरण में खुदाई करके आईडीएक्स ऑब्जेक्ट्स के अनुक्रम द्वारा निर्दिष्ट नेस्टेड मान को निकालता है, यदि कोई मध्यवर्ती चरण शून्य है तो शून्य लौटाता है।
h = { foo: {bar: {baz: 1}}}
h.dig(:foo, :bar, :baz) # => 1
h.dig(:foo, :zot, :xyz) # => nil
g = { foo: [10, 11, 12] }
g.dig(:foo, 1) # => 11
डिफ़ॉल्ट मान सेट करना
डिफ़ॉल्ट रूप से, जो कुंजी मौजूद नहीं है, उसके लिए मान देखने का प्रयास करना nil
लौटेगा। जब गैर-मौजूद कुंजी के साथ हैश एक्सेस किया जाता है, तो आप वैकल्पिक रूप से लौटने के लिए कुछ अन्य मान निर्दिष्ट कर सकते हैं (या लेने की क्रिया)। यद्यपि इसे "डिफ़ॉल्ट मान" के रूप में संदर्भित किया जाता है, इसलिए इसे एकल मान नहीं होना चाहिए; उदाहरण के लिए, यह कुंजी की लंबाई जैसे एक संगणित मूल्य हो सकता है।
हैश का डिफ़ॉल्ट मान इसके निर्माता को दिया जा सकता है:
h = Hash.new(0)
h[:hi] = 1
puts h[:hi] # => 1
puts h[:bye] # => 0 returns default value instead of nil
एक पहले से निर्मित हैश पर एक डिफ़ॉल्ट भी निर्दिष्ट किया जा सकता है:
my_hash = { human: 2, animal: 1 }
my_hash.default = 0
my_hash[:plant] # => 0
यह ध्यान रखना महत्वपूर्ण है कि हर बार नई कुंजी एक्सेस करने पर डिफ़ॉल्ट मान की प्रतिलिपि नहीं बनाई जाती है, जिससे डिफ़ॉल्ट मान एक संदर्भ प्रकार होने पर आश्चर्यजनक परिणाम हो सकते हैं:
# Use an empty array as the default value
authors = Hash.new([])
# Append a book title
authors[:homer] << 'The Odyssey'
# All new keys map to a reference to the same array:
authors[:plato] # => ['The Odyssey']
इस समस्या को दरकिनार करने के लिए, हैश कंस्ट्रक्टर एक ब्लॉक को स्वीकार करता है जिसे हर बार एक नई कुंजी एक्सेस करने पर निष्पादित किया जाता है, और लौटाया गया मान डिफ़ॉल्ट के रूप में उपयोग किया जाता है:
authors = Hash.new { [] }
# Note that we're using += instead of <<, see below
authors[:homer] += ['The Odyssey']
authors[:plato] # => []
authors # => {:homer=>["The Odyssey"]}
ध्यान दें कि ऊपर हमें << के बजाय + = का उपयोग करना था क्योंकि डिफ़ॉल्ट मान स्वचालित रूप से हैश को नहीं सौंपा गया है; << का उपयोग करने से सरणी में जुड़ जाता, लेकिन लेखक [: होमर] अपरिभाषित रह जाते:
authors[:homer] << 'The Odyssey' # ['The Odyssey']
authors[:homer] # => []
authors # => {}
पहुँच पर डिफ़ॉल्ट मान निर्दिष्ट करने में सक्षम होने के साथ-साथ अधिक परिष्कृत चूक की गणना करने के लिए, डिफ़ॉल्ट ब्लॉक को हैश और कुंजी दोनों से पारित किया जाता है:
authors = Hash.new { |hash, key| hash[key] = [] }
authors[:homer] << 'The Odyssey'
authors[:plato] # => []
authors # => {:homer=>["The Odyssey"], :plato=>[]}
आप कार्रवाई करने और / या कुंजी (या कुछ अन्य डेटा) पर निर्भर मान वापस करने के लिए एक डिफ़ॉल्ट ब्लॉक का उपयोग कर सकते हैं:
chars = Hash.new { |hash,key| key.length }
chars[:test] # => 4
आप और अधिक जटिल हैश भी बना सकते हैं:
page_views = Hash.new { |hash, key| hash[key] = { count: 0, url: key } }
page_views["http://example.com"][:count] += 1
page_views # => {"http://example.com"=>{:count=>1, :url=>"http://example.com"}}
पहले से मौजूद हैश पर प्रोक में डिफ़ॉल्ट सेट करने के लिए, default_proc=
उपयोग करें:
authors = {}
authors.default_proc = proc { [] }
authors[:homer] += ['The Odyssey']
authors[:plato] # => []
authors # {:homer=>["The Odyssey"]}
स्वचालित रूप से एक डीप हैश बनाना
हाश के पास उन कुंजियों के लिए एक डिफ़ॉल्ट मान है जो अनुरोध किए गए हैं लेकिन मौजूद नहीं हैं (शून्य):
a = {}
p a[ :b ] # => nil
नया हैश बनाते समय, कोई डिफ़ॉल्ट निर्दिष्ट कर सकता है:
b = Hash.new 'puppy'
p b[ :b ] # => 'puppy'
Hash.new एक ब्लॉक भी लेता है, जो आपको स्वचालित रूप से नेस्टेड हैश का निर्माण करने की अनुमति देता है, जैसे कि पर्ल का स्वतः-व्यवहार व्यवहार या mkdir -p
:
# h is the hash you're creating, and k the key.
#
hash = Hash.new { |h, k| h[k] = Hash.new &h.default_proc }
hash[ :a ][ :b ][ :c ] = 3
p hash # => { a: { b: { c: 3 } } }
कुंजी और मूल्यों को संशोधित करना
आप संशोधित की गई कुंजियों या मूल्यों के साथ एक नया हैश बना सकते हैं, वास्तव में आप इंजेक्शन (AKA, कम ) का उपयोग करके चाबियाँ भी जोड़ या हटा सकते हैं। उदाहरण के लिए कठोर कुंजी और ऊपरी केस मान के साथ हैश का उत्पादन करने के लिए:
fruit = { name: 'apple', color: 'green', shape: 'round' }
# => {:name=>"apple", :color=>"green", :shape=>"round"}
new_fruit = fruit.inject({}) { |memo, (k,v)| memo[k.to_s] = v.upcase; memo }
# => new_fruit is {"name"=>"APPLE", "color"=>"GREEN", "shape"=>"ROUND"}
हैश एक गणनीय है, संक्षेप में कुंजी / मूल्य जोड़े का एक संग्रह है। इसलिए each
, map
और inject
जैसे तरीके हैं।
हैश में प्रत्येक कुंजी / मान युग्म के लिए दिए गए ब्लॉक का मूल्यांकन किया जाता है, पहले रन पर मेमो का मूल्य inject
लिए पारित बीज मान है, हमारे मामले में एक खाली हैश, {}
। बाद के मूल्यांकन के लिए memo
मूल्य पिछले ब्लॉकों के मूल्यांकन का लौटा हुआ मूल्य है, यही कारण है कि हम मूल्य के साथ एक कुंजी सेट करके memo
को संशोधित करते हैं और फिर अंत में memo
वापस करते हैं। अंतिम ब्लॉक मूल्यांकन का रिटर्न वैल्यू हमारे मामले memo
में, inject
का रिटर्न मूल्य है।
अंतिम मूल्य प्रदान करने से बचने के लिए, आप इसके बजाय प्रत्येक_with_object का उपयोग कर सकते हैं:
new_fruit = fruit.each_with_object({}) { |(k,v), memo| memo[k.to_s] = v.upcase }
या यहां तक कि नक्शा :
new_fruit = Hash[fruit.map{ |k,v| [k.to_s, v.upcase] }]
(अधिक विवरण के लिए यह उत्तर देखें, जिसमें जगह में हैश का हेरफेर करना शामिल है।)
ओवर द हेटिंग इटरेटिंग
एक Hash
में Enumerable
मॉड्यूल शामिल है, जो कई पुनरावृत्ति विधियाँ प्रदान करता है, जैसे: Enumerable#each
, Enumerable#each_pair
Enumerable#each
, Enumerable#each_pair
Enumerable#each
Enumerable#each_key
, और Enumerable#each_value
।
.each
और .each_pair
प्रत्येक कुंजी-मूल्य जोड़ी पर पुनरावृति करें:
h = { "first_name" => "John", "last_name" => "Doe" }
h.each do |key, value|
puts "#{key} = #{value}"
end
# => first_name = John
# last_name = Doe
.each_key
केवल कुंजियों पर .each_key
करता है:
h = { "first_name" => "John", "last_name" => "Doe" }
h.each_key do |key|
puts key
end
# => first_name
# last_name
.each_value
केवल मानों पर पुनरावृत्ति करता है:
h = { "first_name" => "John", "last_name" => "Doe" }
h.each_value do |value|
puts value
end
# => John
# Doe
.each_with_index
तत्वों पर पुनरावृत्ति करता है और पुनरावृत्ति का सूचकांक प्रदान करता है:
h = { "first_name" => "John", "last_name" => "Doe" }
h.each_with_index do |(key, value), index|
puts "index: #{index} | key: #{key} | value: #{value}"
end
# => index: 0 | key: first_name | value: John
# index: 1 | key: last_name | value: Doe
Arrays से और इससे रूपांतरण
Hashes स्वतंत्र रूप से और सरणियों से परिवर्तित किया जा सकता है। एक सरणी में कुंजी / मान जोड़े के हैश को परिवर्तित करने से जोड़ी के लिए नेस्टेड सरणियों वाले सरणी का उत्पादन होगा:
{ :a => 1, :b => 2 }.to_a # => [[:a, 1], [:b, 2]]
विपरीत दिशा में एक ही प्रारूप की एक सरणी से एक हैश बनाया जा सकता है:
[[:x, 3], [:y, 4]].to_h # => { :x => 3, :y => 4 }
इसी तरह, Hash[]
और बारी-बारी से कुंजी और मूल्यों की एक सूची का उपयोग करते हुए Hash[]
का आरंभ किया जा सकता है:
Hash[:a, 1, :b, 2] # => { :a => 1, :b => 2 }
या दो मूल्यों के साथ सरणियों के एक सरणी से:
Hash[ [[:x, 3], [:y, 4]] ] # => { :x => 3, :y => 4 }
चपटे flatten()
का उपयोग करते हुए flatten()
को वैकल्पिक कुंजियों और मूल्यों के एक सरणी में वापस परिवर्तित किया जा सकता है:
{ :a => 1, :b => 2 }.flatten # => [:a, 1, :b, 2]
करने के लिए और एक सरणी से आसान रूपांतरण की अनुमति देता है Hash
कई के साथ अच्छी तरह से काम करने के लिए Enumerable
जैसे तरीकों collect
और zip
:
Hash[('a'..'z').collect{ |c| [c, c.upcase] }] # => { 'a' => 'A', 'b' => 'B', ... }
people = ['Alice', 'Bob', 'Eve']
height = [5.7, 6.0, 4.9]
Hash[people.zip(height)] # => { 'Alice' => 5.7, 'Bob' => '6.0', 'Eve' => 4.9 }
हैश की सभी कुंजी या मान प्राप्त करना
{foo: 'bar', biz: 'baz'}.keys # => [:foo, :biz]
{foo: 'bar', biz: 'baz'}.values # => ["bar", "baz"]
{foo: 'bar', biz: 'baz'}.to_a # => [[:foo, "bar"], [:biz, "baz"]]
{foo: 'bar', biz: 'baz'}.each #<Enumerator: {:foo=>"bar", :biz=>"baz"}:each>
ओवरशाइडिंग हैश फ़ंक्शन
रूबी हैश विधियों hash
और eql?
उपयोग करें eql?
हैश ऑपरेशन करने और आंतरिक हैश डिब्बे में हैश में संग्रहीत वस्तुओं को असाइन करने के लिए। रूबी में hash
का डिफ़ॉल्ट कार्यान्वयन हैशेड ऑब्जेक्ट के सभी सदस्य क्षेत्रों पर बड़बड़ाना हैश फ़ंक्शन है । इस व्यवहार को ओवरराइड करने के लिए hash
और eql?
को ओवरराइड करना संभव है eql?
तरीकों।
अन्य हैश कार्यान्वयन के रूप में, दो वस्तुओं a और b, एक ही बाल्टी को hashed किया जाएगा यदि a.hash == b.hash
और समान माना जाएगा यदि a.eql?(b)
। इस प्रकार, hash
और eql?
एक को यह सुनिश्चित करने के लिए ध्यान रखना चाहिए कि क्या a
और b
ईक्वल के तहत बराबर हैं eql?
उन्हें उसी hash
मान को वापस करना चाहिए। अन्यथा इसके परिणामस्वरूप डुप्लिकेट प्रविष्टियाँ हैश में हो सकती हैं। इसके विपरीत, hash
कार्यान्वयन में खराब विकल्प एक ही हैश बाल्टी को साझा करने के लिए कई वस्तुओं का नेतृत्व कर सकता है, प्रभावी रूप से O (1) लुक-अप समय को नष्ट करने और O (n) को कॉल करने के लिए eql?
सभी वस्तुओं पर।
नीचे दिए गए उदाहरण में केवल कक्षा A
का उदाहरण एक कुंजी के रूप में संग्रहीत किया गया है, क्योंकि इसे पहले जोड़ा गया था:
class A
def initialize(hash_value)
@hash_value = hash_value
end
def hash
@hash_value # Return the value given externally
end
def eql?(b)
self.hash == b.hash
end
end
class B < A
end
a = A.new(1)
b = B.new(1)
h = {}
h[a] = 1
h[b] = 2
raise "error" unless h.size == 1
raise "error" unless h.include? b
raise "error" unless h.include? a
फ़िल्टरिंग हैश
select
रिटर्न एक नया hash
जो करने के लिए ब्लॉक का मूल्यांकन के लिए कुंजी-मान जोड़ों के साथ true
।
{ :a => 1, :b => 2, :c => 3 }.select { |k, v| k != :a && v.even? } # => { :b => 2 }
जब आपको फ़िल्टर ब्लॉक में कुंजी या मान की आवश्यकता नहीं होगी, तो उस स्थान पर एक _
का उपयोग करने के लिए कन्वेंशन है:
{ :a => 1, :b => 2, :c => 3 }.select { |_, v| v.even? } # => { :b => 2 }
{ :a => 1, :b => 2, :c => 3 }.select { |k, _| k == :c } # => { :c => 3 }
reject
एक नया रिटर्न hash
कुंजी-मान जोड़ों के साथ जो करने के लिए ब्लॉक का मूल्यांकन के लिए false
:
{ :a => 1, :b => 2, :c => 3 }.reject { |_, v| v.even? } # => { :a => 1, :c => 3 }
{ :a => 1, :b => 2, :c => 3 }.reject { |k, _| k == :b } # => { :a => 1, :c => 3 }
Hashes पर संचालन सेट करें
हश्र का अन्तःकरण
दो हैश के चौराहे को प्राप्त करने के लिए, साझा की गई कुंजियों को वापस लौटाएं, जिनके मूल्य बराबर हैं:
hash1 = { :a => 1, :b => 2 } hash2 = { :b => 2, :c => 3 } hash1.select { |k, v| (hash2.include?(k) && hash2[k] == v) } # => { :b => 2 }
हैश का संघ (विलय):
एक हैश में कुंजियाँ अद्वितीय हैं, यदि दोनों हैश में एक कुंजी होती है जिसे विलय किया जाना होता है, तो जिस हैश में
merge
होता है उसे ओवरराइट किया जाता है:hash1 = { :a => 1, :b => 2 } hash2 = { :b => 4, :c => 3 } hash1.merge(hash2) # => { :a => 1, :b => 4, :c => 3 } hash2.merge(hash1) # => { :b => 2, :c => 3, :a => 1 }