प्रोग्रामिंग में इटरेशन का मतलब है कोड के एक ब्लॉक को कई बार दोहराने की प्रक्रिया।
यह while लूप और until लूप जैसी चीज़ों की मदद से किया जा सकता है।
यह रिकर्सन से भी किया जा सकता है, यानी ऐसे फंक्शन से जो खुद को कॉल करता है।
लेकिन अक्सर आपको चीज़ों के किसी संग्रह पर इटरेशन करना होता है, जैसे Array, Range या String पर।
Crystal में Array और Range दोनों क्लास में Enumerable मॉड्यूल शामिल है, जो एलिमेंट पर इटरेशन करने के लिए कई मेथड देता है।
वहीं, String क्लास में अक्षरों पर इटरेशन करने के लिए अपने अलग मेथड हैं।
Crystal में दूसरी भाषाओं जैसा for स्टेटमेंट भी नहीं है।
इसकी जगह यहाँ कई मेथड हैं जिनसे इटरेशन किया जा सकता है।
किसी संग्रह पर इटरेशन करने का सबसे आम तरीका each मेथड है, जो संग्रह का हर एलिमेंट ब्लॉक को देता है।
यह Range के साथ आसानी से किया जा सकता है।
मान लीजिए आप 1 से 3 के बीच लूप चलाना चाहते हैं, तो आप each मेथड से इस रेंज पर इटरेशन कर सकते हैं।
(1..3).each do |n|
puts n
end
# Output:
# 1
# 2
# 3
और भी आसान तरीका: अगर आपको बस कुछ तय संख्या में इटरेशन करना है, तो Int क्लास का times मेथड इस्तेमाल कर सकते हैं।
3.times do |n|
puts n
end
# Output:
# 0
# 1
# 2
String पर इटरेशन करनाString अक्षरों का एक क्रम है और यह Enumerable मॉड्यूल में शामिल नहीं है, इसलिए अक्षरों पर इटरेशन करने के लिए इसके अपने मेथड हैं।
String पर इटरेशन करने का सबसे आम तरीका each_char मेथड है, जो String का हर अक्षर ब्लॉक को देता है।
each_char मेथड ब्लॉक को Char ऑब्जेक्ट देता है, String ऑब्जेक्ट नहीं।
str = "hello"
str.each_char { |char| puts char }
# Output:
# h
# e
# l
# l
# o
String पर इटरेशन करने का एक और तरीका each_line मेथड है।
यह मेथड ज़्यादातर तब इस्तेमाल होता है जब किसी फाइल को एक-एक लाइन पढ़ना हो।
str = "hello\nworld"
str.each_line do |line|
puts line
end
# Output:
# hello
# world
Enumerable मॉड्यूल शामिल होEnumerable मॉड्यूल किसी संग्रह के एलिमेंट पर इटरेशन करने के लिए कई मेथड देता है।
जिन संग्रहों में Enumerable मॉड्यूल शामिल होता है, वे हैं Array, Range, Hash, Set और कुछ और; इनमें से बाद वाले आगे के कॉन्सेप्ट में समझाए जाएँगे।
Array पर इटरेशन करने का सबसे आम तरीका each मेथड है, जो Array का हर एलिमेंट ब्लॉक को देता है।
arr = [5, 2, 3]
arr.each do |element|
puts element
end
# Output:
# 5
# 2
# 3
map मेथड Array पर इटरेशन करने का एक और तरीका है। यह एक नया Array लौटाता है जिसमें हर एलिमेंट पर ब्लॉक लगाने के परिणाम होते हैं।
यह each मेथड जैसा ही है, पर यह बदले हुए एलिमेंट वाला नया Array लौटाता है।
किसी संग्रह के हर एलिमेंट पर फंक्शन लगाना आम बात है, और ऐसे में यह बदलाव बहुत काम आता है।
arr = [1, 2, 3]
new_arr = arr.map do |element|
element * 2
end
new_arr
# => [2, 4, 6]
if जैसी शर्त लगाकर आप यह भी तय कर सकते हैं कि किन एलिमेंट को बदलना है।
arr = [1, 2, 3]
new_arr = arr.map do |element|
if element.odd?
element * 2
else
element
end
end
new_arr
# => [2, 2, 6]
कभी-कभी आपको यह जानना होता है कि जिस एलिमेंट पर इटरेशन कर रहे हैं उसका इंडेक्स क्या है। इसके लिए आप each_with_index या map_with_index मेथड इस्तेमाल कर सकते हैं।
यह ब्लॉक को हर एलिमेंट और उसका इंडेक्स देता है। यह मेथड शुरुआती इंडेक्स बताने के लिए एक वैकल्पिक आर्गुमेंट भी लेता है।
arr = [1, 2, 3]
arr.each_with_index(4) do |element, index|
puts "Element: #{element}, Index: #{index}"
end
# Output:
# Element: 1, Index: 4
# Element: 2, Index: 5
# Element: 3, Index: 6
ध्यान दीजिए कि each_char_with_index मेथड String ऑब्जेक्ट के लिए भी उपलब्ध है।
sum मेथड संग्रह के सारे एलिमेंट का जोड़ लौटाता है। यह जोड़ने से पहले एलिमेंट बदलने के लिए एक वैकल्पिक ब्लॉक भी लेता है।
यह जोड़ की शुरुआती वैल्यू बताने के लिए एक वैकल्पिक आर्गुमेंट भी लेता है।
arr = [1, 2, 3]
arr.sum
# => 6
arr.sum(2) { |n| n * 2 }
# => 14
reduce या दूसरी भाषाओं में जिसे fold कहा जाता है, ऐसा मेथड है जो एक जोड़ने वाले तरीके और एक शुरुआती वैल्यू के साथ संग्रह के सारे एलिमेंट को मिला देता है।
reduce मेथड में एक एक्युमुलेटर होता है जो ब्लॉक को दिया जाता है, और यह एक्युमुलेटर पिछले इटरेशन का परिणाम होता है।
इस तरह यह एक रिकर्सिव प्रक्रिया बन जाती है जो संग्रह के सारे एलिमेंट को मिला देती है।
arr = [1, 2, 3]
arr.reduce(0) do |acc, n|
acc + n
end
# => 6
reduce sum जैसा लग सकता है, लेकिन reduce ज़्यादा लचीला है क्योंकि इसमें आप एक्युमुलेटर की शुरुआती वैल्यू और जोड़ने का तरीका खुद तय कर सकते हैं।
reduce की मदद से sum, count और दूसरे मेथड बनाए जा सकते हैं।
Spellbound Steel नाम के कार्ड गेम में आपके पास कार्ड का एक डेक होता है। इस डेक में या तो Warrior, Mage और Rogue जैसे अलग-अलग पात्रों वाले कार्ड होते हैं, या Fireball, Ice Storm और Lightning Bolt जैसे अलग-अलग जादू वाले कार्ड। गेम में दो से चार खिलाड़ी होते हैं, और लक्ष्य यह है कि आप ज़्यादा पावर लेवल वाले कार्ड खेलकर बाकी खिलाड़ियों को हरा दें।
आप गेम में बढ़त बनाना चाहते हैं, इसलिए कार्डों के पावर लेवल की गणना करने, उन्हें क्रमबद्ध करने और उनकी तुलना करने के लिए अलग-अलग मेथड बनाते हैं।
आपको पक्का पता नहीं है कि कोई कार्ड डेक में है या नहीं। इसलिए आप एक ऐसा मेथड चाहते हैं जो बताए कि जिस तरह का कार्ड आप ढूँढ़ रहे हैं, वह डेक में सबसे पहले कहाँ मिलता है। और अगर वह कार्ड डेक में नहीं है, तो यह भी पता चल जाना चाहिए।
एक मेथड SpellboundSteel.find_card? बनाइए जो String कार्डों का एक Array और उस String कार्ड को लेता है जिसे ढूँढ़ना है। मेथड को डेक के उस पहले कार्ड का इंडेक्स लौटाना चाहिए जो ढूँढ़ने वाले कार्ड से मेल खाता है। अगर कार्ड डेक में नहीं है, तो मेथड को nil लौटाना चाहिए।
cards = ["Warrior", "Mage", "Rogue", "Fireball", "Ice Storm", "Lightning Bolt", "Mage"]
SpellboundSteel.find_card?(cards, "Mage")
# => 1
कार्ड पढ़ने में आसान लगें, इसलिए आप कार्ड के नामों के सभी अक्षर बड़े करना चाहते हैं। इससे कार्ड खेलते समय आपको कार्ड के नाम आसानी से दिख जाते हैं।
एक मेथड SpellboundSteel.capitalize_cards बनाइए जो String कार्डों का एक Array लेता है और सभी अक्षर बड़े किए हुए कार्ड लौटाता है।
cards = ["warrior", "mage", "rogue", "fireball", "ice storm", "lightning bolt"]
SpellboundSteel.capitalize_cards(cards)
# => ["Warrior", "Mage", "Rogue", "Fireball", "Ice Storm", "Lightning Bolt"]
गेम में सभी कार्डों के पावर लेवल की गणना करना ज़रूरी है। सभी कार्डों का पावर इस तालिका में देखा जा सकता है:
| कार्ड का प्रकार | पावर लेवल |
|---|---|
| Warrior | 10 |
| Mage | 20 |
| Rogue | 30 |
| Fireball | 15 |
| Ice Storm | 25 |
| Lightning Bolt | 35 |
एक मेथड SpellboundSteel.calculate_power_level बनाइए जो String कार्डों का एक Array लेता है और सभी कार्डों का कुल पावर लेवल लौटाता है।
cards = ["Warrior", "Mage", "Rogue", "Fireball", "Ice Storm", "Lightning Bolt"]
SpellboundSteel.calculate_power_level(cards)
# => 135
गेम में कुछ कार्ड शापित कार्ड कहलाते हैं। ये छिपे हुए कार्ड होते हैं, जिन्हें सिर्फ वही खिलाड़ी डिकोड कर सकता है जिसने उन्हें खेला हो। कार्ड को डिकोड करने के लिए आपको कार्ड के नाम में हर दूसरा अक्षर चुनकर उसे हटाना होता है। इससे कार्ड का नाम मिल जाता है।
एक मेथड SpellboundSteel.decode_card बनाइए जो एक String कार्ड लेता है और डिकोड किया हुआ कार्ड लौटाता है।
SpellboundSteel.decode_card("Wbalrrrlimoqr")
# => "Warrior"
Exercism पर साइन अप कीजिए और Crystal को 26 कॉन्सेप्ट142 अभ्यास तथा असली इंसानों से मिलने वाली मेंटरिंग के साथ सीखिए और उसमें महारत हासिल कीजिए, वह भी बिल्कुल मुफ्त।