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

रूबी का जादुई संख्यात्मक मॉड्यूल

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

Enumerable , #each और Enumerator

गणना वस्तुओं पर ट्रैवर्सिंग को संदर्भित करता है। रूबी में, हम किसी वस्तु को गणना योग्य कहते हैं जब यह वस्तुओं के एक सेट और उनमें से प्रत्येक पर लूप करने की विधि का वर्णन करता है।

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

नोट :कुछ तरीके, जैसे #count और #take Array . पर वर्ग, हैं 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 के तरीकों में सी कार्यान्वयन है, लेकिन ऊपर दिया गया उदाहरण मोटे तौर पर दिखाता है कि कैसे #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 पर पास किए गए ब्लॉक को कॉल करके अपने लाभ के लिए सूची की पुनरावर्ती प्रकृति का उपयोग कर सकते हैं। , और #each . पर कॉल कर रहे हैं @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
 
  def each(&block)
    block.call(@head)
    @tail.each(&block) if @tail
  end
end

कॉल करते समय #each हमारी लिंक्ड सूची के एक उदाहरण पर, यह वर्तमान @head . के साथ पारित ब्लॉक को कॉल करता है . फिर, यह लिंक की गई सूची में से प्रत्येक को @tail . में कॉल करता है जब तक कि टेल nil न हो ।

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

अब जबकि हमारी लिंक की गई सूची #each . का जवाब देती है , हम include Enumberable हमारी सूची को गणनीय बनाने के लिए।

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 उदाहरण

अब हम अपनी लिंक की गई सूची में सभी मानों पर लूप कर सकते हैं, लेकिन हम अभी तक गणना योग्य कार्यों को श्रृंखलाबद्ध नहीं कर सकते हैं। ऐसा करने के लिए, हमें एक Enumerator return लौटाना होगा उदाहरण के लिए जब हमारा #each फ़ंक्शन को बिना ब्लॉक के कॉल किया जाता है।

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}

कोड की नौ पंक्तियाँ और एक शामिल

#each . को लागू करके Enumerable . का उपयोग करके मॉड्यूल और वापसी Enumerator अपने आप से वस्तुओं, हम कोड की नौ पंक्तियों और एक शामिल जोड़कर अपनी लिंक की गई सूची को सुपरचार्ज करने में सक्षम थे।

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


  1. रूबी में लैम्ब्डा का उपयोग करना

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

  1. रूबी में 9 नई सुविधाएँ 2.6

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

  1. रूबी एन्यूमरेबल मॉड्यूल के लिए एक बुनियादी गाइड (+ मेरी पसंदीदा विधि)

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