Computer >> कंप्यूटर ट्यूटोरियल >  >> प्रोग्रामिंग >> Ruby

रूबी के Enumerable मॉड्यूल में महारत: शक्तिशाली कलेक्शन मेथड्स अनलॉक करें

रूबी मैजिक के एक और एपिसोड का समय! इस बार, हम रूबी की सबसे जादुई विशेषताओं में से एक को देखेंगे, जो उन अधिकांश मेथड्स को प्रदान करती है जिनका आप रूबी की एन्युमरेबल क्लासेस जैसे Array, Hash और Range के साथ काम करते समय उपयोग करेंगे। इस प्रक्रिया में, हम सीखेंगे कि आप एन्युमरेबल ऑब्जेक्ट्स के साथ क्या कर सकते हैं, एन्युमरेशन कैसे काम करता है, और एक सिंगल मेथड को लागू करके ऑब्जेक्ट को एन्युमरेबल कैसे बनाया जाए।

Enumerable, #each और Enumerator

एन्युमरेशन ऑब्जेक्ट्स पर ट्रैवर्स करने को संदर्भित करता है। रूबी में, हम एक ऑब्जेक्ट को एन्युमरेबल कहते हैं जब यह आइटम्स के एक सेट और उनमें से प्रत्येक पर लूप करने के मेथड का वर्णन करता है।

बिल्ट-इन एन्युमरेबल्स को Enumerable मॉड्यूल को शामिल करके उनकी एन्युमरेशन सुविधाएँ मिलती हैं, जो #include?, #count, #map, #select और #uniq जैसे मेथड्स प्रदान करता है, दूसरों के अलावा। ऐरे और हैश से जुड़े अधिकांश मेथड्स वास्तव में इन क्लासेस में स्वयं लागू नहीं होते, वे शामिल होते हैं।

नोट: कुछ मेथड्स, जैसे Array क्लास पर #count और #take, हैं विशेष रूप से ऐरे के लिए लागू किए गए हैं बजाय Enumerable मॉड्यूल से उन का उपयोग करने के। यह आमतौर पर ऑपरेशन को तेज़ बनाने के लिए किया जाता है।

Enumerable मॉड्यूल #each नामक मेथड पर निर्भर करता है, जिसे किसी भी क्लास में लागू किया जाना चाहिए जिसमें यह शामिल है। जब एक ब्लॉक के साथ ऐरे पर कॉल किया जाता है, तो #each मेथड ऐरे के प्रत्येक एलिमेंट के लिए ब्लॉक को निष्पादित करेगा।

irb> [1,2,3].each { |i| puts "* #{i}" }
* 1
* 2
* 3
=> [1,2,3]

यदि हम ब्लॉक पास किए बिना ऐरे पर #each मेथड कॉल करते हैं, तो हमें Enumerator का एक इंस्टेंस प्राप्त होगा।

irb> [1,2,3].each
=> #<Enumerator: [1, 2, 3]:each>

Enumerator के इंस्टेंस वर्णन करते हैं कि किसी ऑब्जेक्ट पर कैसे इटरेट करना है। एन्युमरेटर्स ऑब्जेक्ट्स पर मैन्युअली इटरेट करते हैं और एन्युमरेशन चेन करते हैं।

irb> %w(dog cat mouse).each.with_index { |a, i| puts "#{a} is at position #{i}" }
dog is at position 0
cat is at position 1
mouse is at position 2
=> ["dog", "cat", "mouse"]

#with_index मेथड बदले हुए एन्युमरेटर्स कैसे काम करते हैं इसका एक अच्छा उदाहरण है। इस उदाहरण में, ऐरे पर #each कॉल करके एन्युमरेटर लौटाया जाता है। फिर, प्रत्येक ऐरे एलिमेंट में इंडेक्स जोड़ने के लिए #with_index कॉल किया जाता है ताकि प्रत्येक एलिमेंट का इंडेक्स प्रिंट किया जा सके।

ऑब्जेक्ट्स को एन्युमरेबल बनाना

हुड के नीचे, #max, #map और #take जैसे मेथड्स कार्य करने के लिए #each मेथड पर भरोसा करते हैं।

def max
  max = nil
  each do |item|
    if !max || item > max
      max = item
    end
  end
  max
end

आंतरिक रूप से, Enumerable के मेथड्स के C कार्यान्वयन हैं, लेकिन उपरोक्त उदाहरण मोटे तौर पर दिखाता है कि #max कैसे काम करता है। #each का उपयोग करके सभी मानों पर लूप करके और उच्चतम को याद करके, यह अधिकतम मान लौटाता है।

def map(&block)
  new_list = []
  each do |item|
    new_list << block.call(item)
  end
  new_list
end

#map फंक्शन पास किए गए ब्लॉक को प्रत्येक आइटम के साथ कॉल करता है और सभी मानों पर लूप करने के बाद लौटाने के लिए परिणाम को एक नई सूची में रखता है।

चूंकि Enumerable के सभी मेथड्स कुछ हद तक #each मेथड का उपयोग करते हैं, कस्टम क्लास को एन्युमरेबल बनाने में हमारा पहला कदम #each मेथड को लागू करना है।

#each लागू करना

#each फंक्शन को लागू करके और क्लास में Enumerable मॉड्यूल को शामिल करके, यह एन्युमरेबल बन जाता है और #min, #take और #inject जैसे मेथड्स मुफ्त में प्राप्त करता है।

हालांकि अधिकांश स्थितियां मौजूदा ऑब्जेक्ट जैसे ऐरे पर वापस जाने और उस पर #each मेथड कॉल करने की अनुमति देती हैं, आइए एक उदाहरण देखें जहां हमें इसे स्क्रैच से खुद लिखना होगा। इस उदाहरण में, हम #each को लिंक्ड लिस्ट पर लागू करेंगे ताकि यह एन्युमरेबल बन जाए।

लिंक्ड लिस्ट्स: ऐरे के बिना लिस्ट्स

लिंक्ड लिस्ट डेटा एलिमेंट्स का संग्रह है, जिसमें प्रत्येक एलिमेंट अगले की ओर इशारा करता है। लिस्ट में प्रत्येक एलिमेंट के दो मान होते हैं, जिन्हें हेड और टेल नाम दिया गया है। हेड एलिमेंट का मान रखता है, और टेल लिस्ट के बाकी हिस्से का लिंक है।

[42, [12, [73, nil]] 

तीन मानों (42, 12 और 73) वाली लिंक्ड लिस्ट के लिए, पहले एलिमेंट का हेड 42 है, और टेल दूसरे एलिमेंट का लिंक है। दूसरे एलिमेंट का हेड 12 है, और टेल तीसरे एलिमेंट को रखता है। तीसरे एलिमेंट का हेड 73 है, और टेल nil है, जो लिस्ट के अंत को इंगित करता है।

रूबी में, लिंक्ड लिस्ट को @head और @tail नाम के दो इंस्टेंस वेरिएबल्स रखने वाली क्लास का उपयोग करके बनाया जा सकता है।

class LinkedList
  def initialize(head, tail = nil)
    @head, @tail = head, tail
  end
  def <<(item)
    LinkedList.new(item, self)
  end
  def inspect
    [@head, @tail].inspect
  end
end

#<< मेथड लिस्ट में नए मान जोड़ने के लिए उपयोग किया जाता है, जो पास किए गए मान को हेड और पिछली लिस्ट को टेल के रूप में एक नई लिस्ट लौटाकर काम करता है।

इस उदाहरण में, #inspect मेथड जोड़ा गया है ताकि हम लिस्ट में देख सकें कि इसमें कौन से एलिमेंट्स हैं।

irb> LinkedList.new(73) << 12 << 42
=> [42, [12, [73, nil]]]

अब जब हमारे पास लिंक्ड लिस्ट है, तो आइए इस पर #each लागू करें। #each फंक्शन एक ब्लॉक लेता है और ऑब्जेक्ट में प्रत्येक मान के लिए इसे निष्पादित करता है। इसे अपनी लिंक्ड लिस्ट पर लागू करते समय, हम लिस्ट की रिकर्सिव प्रकृति का लाभ उठा सकते हैं पास किए गए ब्लॉक को लिस्ट के @head पर कॉल करके, और @tail पर #each कॉल करके, यदि यह मौजूद है।

class LinkedList
  def initialize(head, tail = nil)
    @head, @tail = head, tail
  end
  def <<(item)
    LinkedList.new(item, self)
  end
  def inspect
    [@head, @tail].inspect
  end
  def each(&block)
    block.call(@head)
    @tail.each(&block) if @tail
  end
end

हमारी लिंक्ड लिस्ट के इंस्टेंस पर #each कॉल करने पर, यह करंट @head के साथ पास किए गए ब्लॉक को कॉल करता है। फिर, यह @tail में लिंक्ड लिस्ट पर each को कॉल करता है जब तक टेल nil न हो।

irb> list = LinkedList.new(73) << 12 << 42
=> [42, [12, [73, nil]]]
irb> list.each { |item| puts item }
42
12
73
=> nil

अब जब हमारी लिंक्ड लिस्ट #each का जवाब देती है, तो हम include Enumerable कर सकते हैं ताकि हमारी लिस्ट एन्युमरेबल बन जाए।

class LinkedList
  include Enumerable
  def initialize(head, tail = nil)
    @head, @tail = head, tail
  end
  def <<(item)
    LinkedList.new(item, self)
  end
  def inspect
    [@head, @tail].inspect
  end
  def each(&block)
    block.call(@head)
    @tail.each(&block) if @tail
  end
end
irb> list = LinkedList.new(73) << 12 << 42
=> [42, [12, [73, nil]]]
irb> list.count
=> 3
irb> list.max
=> 73
irb> list.map { |item| item * item }
=> [1764, 144, 5329]
irb> list.select(&:even?)
=> [42, 12]

Enumerator इंस्टेंस लौटाना

अब हम अपनी लिंक्ड लिस्ट में सभी मानों पर लूप कर सकते हैं, लेकिन हम एन्युमरेबल फंक्शन्स को चेन नहीं कर सकते। ऐसा करने के लिए, जब हमारा #each फंक्शन ब्लॉक के बिना कहा जाता है तो हमें Enumerator इंस्टेंस लौटाने की आवश्यकता होगी।

class LinkedList
  include Enumerable
  def initialize(head, tail = nil)
    @head, @tail = head, tail
  end
  def <<(item)
    LinkedList.new(item, self)
  end
  def inspect
    [@head, @tail].inspect
  end
  def each(&block)
    if block_given?
      block.call(@head)
      @tail.each(&block) if @tail
    else
      to_enum(:each)
    end
  end
end

ऑब्जेक्ट को एन्युमरेटर में लपेटने के लिए, हम इस पर #to_enum मेथड कॉल करते हैं। हम :each पास करते हैं, क्योंकि वह मेथड है जिसका एन्युमरेटर को आंतरिक रूप से उपयोग करना चाहिए।

अब, हमारे #each मेथड को ब्लॉक के बिना कॉल करने से हमें एन्युमरेशन चेन करने की अनुमति मिलेगी।

irb> list = LinkedList.new(73) << 12 << 42
=> [42, [12, [73, nil]]]
irb> list.each
=> #<Enumerator: [42, [12, [73, nil]]]:each>
irb> list.map.with_index.to_h
=> {42=>0, 12=>1, 73=>2}

नौ लाइन्स कोड और एक include

Enumerable मॉड्यूल का उपयोग करके #each को लागू करके और अपने स्वयं के से Enumerator ऑब्जेक्ट्स लौटाकर, हम नौ लाइन्स कोड और एक include जोड़कर अपनी लिंक्ड लिस्ट को सुपरचार्ज करने में सक्षम थे।

यह रूबी में एन्युमरेबल्स का हमारा अवलोकन समाप्त करता है। हमें यह जानकर खुशी होगी कि आपने इस लेख के बारे में क्या सोचा, या यदि आपके कोई प्रश्न हैं। हम जांच और व्याख्या करने के लिए विषयों की तलाश में हमेशा रहते हैं, इसलिए यदि रूबी में कुछ जादुई है जिसे आप पढ़ना चाहेंगे, तो @AppSignal पर हमें बताने में संकोच न करें!

  1. Ruby में Lambdas में महारत हासिल करें: बुनियादी से उन्नत तकनीकें तक Ruby में Lambdas में महारत हासिल करें: बुनियादी से उन्नत तकनीकें तक

    ब्लॉक Ruby का इतना महत्वपूर्ण हिस्सा हैं, उनके बिना भाषा की कल्पना करना कठिन है। लेकिन लैम्ब्डा? कौन लैम्ब्डा से प्यार करता है? आप वर्षों तक बिना एक का उपयोग किए जा सकते हैं। वे लगभग एक बीते युग के अवशेष लगते हैं। ...लेकिन यह पूरी तरह सच नहीं है। लैम्ब्डा की आस्तीन में कुछ दिलचस्प तरकीबें हैं एक बार

  1. Ruby 2.6 में 9 प्रमुख संवर्द्धन का अन्वेषण Ruby 2.6 में 9 प्रमुख संवर्द्धन का अन्वेषण

    Ruby का एक नया संस्करण नई सुविधाओं और प्रदर्शन सुधारों के साथ आ रहा है। क्या आप परिवर्तनों के साथ बने रहना चाहेंगे? आइए एक नज़र डालते हैं! अंतहीन रेंज (Endless Ranges) Ruby 2.5 और पुराने संस्करण पहले से ही अंतहीन रेंज का एक रूप (Float::INFINITY के साथ) का समर्थन करते हैं, लेकिन Ruby 2.6 इसे अगले स्त

  1. रूबी के Enumerable मॉड्यूल में महारत: एक व्यावहारिक गाइड + मेरा शीर्ष मेथड रूबी के Enumerable मॉड्यूल में महारत: एक व्यावहारिक गाइड + मेरा शीर्ष मेथड

    Enumerable क्या है? Enumerable पुनरावृति मेथड्स का एक संग्रह है, एक रूबी मॉड्यूल, और रूबी को एक महान प्रोग्रामिंग भाषा बनाने का एक बड़ा हिस्सा। Enumerable में सहायक मेथड्स शामिल हैं जैसे: map select inject Enumerable मेथड्स उन्हें एक ब्लॉक देकर काम करते हैं। उस ब्लॉक में आप उन्हें बताते हैं कि आप