जब आप अपने कलेक्शन को enumerators के रूप में ट्रीट करते हैं, तो आप #map और #reduce जैसे अपने सभी पसंदीदा फंक्शन का उपयोग कर सकते हैं, बिना कोई अतिरिक्त कोड लिखे। यह बहुत बढ़िया है।
पुराने दिनों में Enumerators को परिभाषित करना
पुराने दिनों में, enumerators को परिभाषित करना थोड़ा मुश्किल था। आपको एक नई क्लास बनानी पड़ती थी, Enumerable मॉड्यूल को शामिल करना पड़ता था, और #each फंक्शन को परिभाषित करना पड़ता था।
Ruby 1.9 के बाद हल्का तरीका
Ruby 1.9 के बाद से, हमारे पास enumerators को ऑन-द-फ्लाई परिभाषित करने का एक अधिक हल्का तरीका है। आइए देखते हैं।
Enumerator क्लास का परिचय
Enumerator क्लास आपको ब्लॉक सिंटैक्स का उपयोग करके एक बार का enumerator परिभाषित करने देती है। नीचे दिए गए उदाहरण में, हम एक enumerator बनाते हैं जो रैंडम नंबर की एक अनंत सीरीज लौटाता है।
e = Enumerator.new do |y|
loop do
y << rand(10) # << ऑपरेटर एक वैल्यू "yield" करता है
end
end
# Enumerator को 10 वैल्यू "yield" करने दें, फिर रुकें
puts e.first(10).inspect # => [6, 6, 7, 2, 2, 9, 6, 8, 2, 1]
आपने देखा होगा कि हम शिफ्ट ऑपरेटर << का एक अजीब तरीके से उपयोग कर रहे हैं। यह y.yield मेथड के लिए एक शॉर्टकट है। आप enumerator में प्रत्येक आइटम के लिए इसे कॉल करेंगे। अगर यह सब थोड़ा जादुई लगता है, तो चिंता न करें। यह है।
कलेक्शन का आकार
Ruby के लेज़ी enumerators के लिए कलेक्शन के आकार का पता लगाना एक समस्या है। कलेक्शन में आइटम गिनने के लिए, आपको पूरे कलेक्शन को लोड करना होगा - जो लेज़ी enumerators का उपयोग करने के पूरे उद्देश्य के खिलाफ है।
एक समाधान है, एक तरह का। यदि आप enumerator बनाते समय कलेक्शन का आकार जानते हैं, तो आप इसे प्रदान कर सकते हैं।
# यदि आपके पास लंबाई है तो इसे कंस्ट्रक्टर में आर्गुमेंट के रूप में पास करें
e = Enumerator.new(10) do |y|
10.times { y << rand }
end
मेरा वास्तविक-विश्व उदाहरण
कल ही मैं Honeybadger की नई डॉक्यूमेंटेशन साइट पर काम कर रहा था। यह Jekyll का उपयोग करके बनाया गया है, और मैं <h2> और <h3> टैग के आधार पर एक टेबल ऑफ कंटेंट्स बनाने के लिए एक प्लगइन लिख रहा था।
<h3> टैग का पता लगाना थोड़ा अजीब है जो <h2> टैग द्वारा परिभाषित सेक्शन से संबंधित हैं। आपको nokogiri का उपयोग करके HTML को पार्स करना होगा, और फिर परिणामी डॉक्यूमेंट को स्कैन करना होगा। इसलिए मैंने उस कोड को अलग किया और इसे एक Enumerator बना दिया। यह ऐसा दिखता है।
def subheadings(el)
Enumerator.new do |y|
next_el = el.next_sibling
while next_el && next_el.name != "h2"
if next_el.name == "h3"
y << next_el
end
next_el = next_el.next_sibling
end
end
end