এনুমেরেবলস (Enumerables) এবং ইটারেটরস (Iterators) রুবিতে এমন কনসেপ্ট, যা ডেটা সংগ্রহের (যেমন অ্যারে, হ্যাশ, সেট) উপাদানগুলির উপর কাজ করতে ব্যবহৃত হয়। এই কনসেপ্টগুলো আপনাকে একে একে উপাদানগুলো অ্যাক্সেস করার এবং তাদের সাথে বিভিন্ন অপারেশন করার সুবিধা দেয়। রুবির Enumerable মডিউল এবং Iterator মেথড ব্যবহারের মাধ্যমে এগুলিকে খুব সহজে কার্যকর করা যায়।
১. Enumerable Module (এনুমেরেবল মডিউল)
Enumerable রুবির একটি মডিউল যা ডেটা সংগ্রহ (যেমন অ্যারে, হ্যাশ, সেট) এর সাথে কাজ করতে ব্যবহৃত হয়। এই মডিউলটি এমন সব মেথড সরবরাহ করে, যা বিভিন্ন ধরণের সংগ্রহের উপর সাধারণ কাজ করতে সাহায্য করে।
মডিউল ডিফাইন করা (Defining an Enumerable)
এনুমেরেবল মডিউলটি ব্যবহার করতে, আপনাকে একটি ক্লাসে include Enumerable যুক্ত করতে হবে, যাতে সেই ক্লাসটি এনুমেরেবল মেথডগুলি ব্যবহার করতে পারে।
module MyEnumerable
include Enumerable
def initialize(*items)
@items = items
end
def each
@items.each { |item| yield item }
end
end
class MyCollection
include MyEnumerable
end
collection = MyCollection.new(1, 2, 3, 4, 5)
collection.each { |item| puts item }এখানে, each মেথডের মাধ্যমে MyCollection ক্লাসের উপাদানগুলো একে একে প্রিন্ট করা হচ্ছে। Enumerable মডিউল স্বয়ংক্রিয়ভাবে অন্যান্য অনেক মেথড (যেমন map, select, reduce, ইত্যাদি) প্রদান করে।
২. Iterators (ইটারেটরস)
ইটারেটরস হল সেই মেথডগুলি যা একটি ডেটা সংগ্রহের উপর একে একে অপারেশন চালানোর জন্য ব্যবহৃত হয়। রুবিতে each, map, select, reject ইত্যাদি ইটারেটর মেথড সরবরাহ করা হয়।
each ইটারেটর
each মেথডটি ডেটা সংগ্রহের প্রতিটি উপাদানকে একে একে প্রসেস করতে ব্যবহৃত হয়।
arr = [1, 2, 3, 4, 5]
arr.each { |number| puts number * 2 }এখানে, each মেথডের মাধ্যমে প্রতিটি উপাদানকে ২ দ্বারা গুণ করা হয়েছে।
map ইটারেটর
map মেথডটি একটি নতুন অ্যারে তৈরি করে, যার প্রতিটি উপাদানকে মূল অ্যারের উপাদানের উপর কিছু অপারেশন করা হয়।
arr = [1, 2, 3, 4, 5]
result = arr.map { |number| number * 2 }
puts result # Output: [2, 4, 6, 8, 10]এখানে, map মেথডের মাধ্যমে নতুন অ্যারে তৈরি করা হয়েছে, যার প্রতিটি উপাদান পূর্ববর্তী অ্যারের উপাদানের ২ গুণ।
select এবং reject ইটারেটর
select: এটি একটি নতুন অ্যারে তৈরি করে, যেখানে শর্ত পুরণ করা উপাদানগুলি থাকে।reject: এটি একটি নতুন অ্যারে তৈরি করে, যেখানে শর্ত পুরণ না করা উপাদানগুলি থাকে।
arr = [1, 2, 3, 4, 5]
# select example
even_numbers = arr.select { |number| number.even? }
puts even_numbers # Output: [2, 4]
# reject example
odd_numbers = arr.reject { |number| number.even? }
puts odd_numbers # Output: [1, 3, 5]এখানে, select মেথডে এমন উপাদানগুলো নির্বাচন করা হয়েছে যেগুলো even (যুগল সংখ্যা), এবং reject মেথডে এমন উপাদানগুলো বাদ দেওয়া হয়েছে যেগুলো even।
reduce এবং inject ইটারেটর
reduce (বা inject) মেথডটি একটি অ্যারের সকল উপাদানকে একটি একক মানে রূপান্তরিত করতে ব্যবহৃত হয়।
arr = [1, 2, 3, 4, 5]
sum = arr.reduce(0) { |sum, number| sum + number }
puts sum # Output: 15এখানে, reduce মেথডের মাধ্যমে অ্যারের সকল উপাদান যোগ করে একটি একক মান তৈরি করা হয়েছে (এখানে 0 হলো শুরু মান)।
৩. সোর্সে এনুমেরেবল মেথডস
এখানে কিছু গুরুত্বপূর্ণ এনুমেরেবল মেথডের উদাহরণ দেওয়া হলো, যা অ্যারে বা অন্যান্য সংগ্রহের উপাদানের সাথে কাজ করতে ব্যবহৃত হয়:
each_with_index
arr = ["apple", "banana", "cherry"]
arr.each_with_index do |item, index|
puts "#{index + 1}. #{item}"
endএখানে, each_with_index মেথডের মাধ্যমে প্রতিটি উপাদান এবং তার ইনডেক্স প্রিন্ট করা হয়েছে।
find (বা detect)
arr = [1, 2, 3, 4, 5]
result = arr.find { |number| number > 3 }
puts result # Output: 4এখানে, find মেথডটি প্রথম উপাদান খুঁজে বের করেছে যা শর্ত পূর্ণ করে (এখানে number > 3)।
sort এবং reverse
arr = [5, 3, 8, 1, 4]
puts arr.sort # Output: [1, 3, 4, 5, 8]
puts arr.reverse # Output: [4, 1, 8, 3, 5]এখানে, sort মেথড অ্যারের উপাদানগুলো ঊর্ধ্বক্রমে সাজিয়েছে, এবং reverse মেথড উপাদানগুলোর অর্ডার উল্টে দিয়েছে।
৪. Enumerable এবং Iterators এর মধ্যে পার্থক্য
- Enumerable একটি মডিউল, যা ডেটা সংগ্রহের উপর কাজ করার জন্য অনেক গুরুত্বপূর্ণ মেথড সরবরাহ করে (যেমন
map,select,reduce,eachইত্যাদি)। - Iterator হলো এমন মেথড যা একটি ডেটা সংগ্রহের উপর একে একে অপারেশন চালানোর জন্য ব্যবহৃত হয়, এবং এটি একটি অংশ হিসেবে
Enumerableমডিউলের মধ্যে অন্তর্ভুক্ত।
সারসংক্ষেপ
রুবির এনুমেরেবলস এবং ইটারেটরস আমাদের ডেটা সংগ্রহের উপাদানগুলির উপর বিভিন্ন কার্যক্রম পরিচালনা করতে সাহায্য করে। each, map, select, reduce এবং inject ইটারেটর মেথডগুলি সহজে ডেটা প্রসেসিংয়ের কাজগুলো করে, এবং Enumerable মডিউলটি সমস্ত ইটারেটর মেথড সরবরাহ করে। এগুলি রুবি কোডকে আরও পরিষ্কার, কার্যকর এবং পুনঃব্যবহারযোগ্য করে তোলে।
রুবিতে Enumerable মডিউল এমন একটি মডিউল যা বিভিন্ন ধরনের ইটারেবল (iterable) কনটেইনারের জন্য একাধিক সাধারণ মেথড প্রদান করে। এটি প্রধানত Array, Hash, Range, এবং অন্যান্য ইটারেবল ডেটা স্ট্রাকচারের জন্য ব্যবহৃত হয়। Enumerable মডিউলটি ইটারেশন এবং অন্যান্য উচ্চ স্তরের ফাংশনালিটি (যেমন map, reduce, select, ইত্যাদি) প্রদান করে, যা প্রোগ্রামিংয়ে কোড সংক্ষেপ এবং কার্যকরী করতে সহায়তা করে।
রুবি ভাষার বেশিরভাগ কালেকশন ক্লাস (যেমন Array, Hash, Range, ইত্যাদি) Enumerable মডিউল ইনক্লুড করে থাকে। এর মাধ্যমে ক্লাসগুলো ইটারেশন সম্পর্কিত অনেক সুবিধা পায় এবং তাদের সাথে সহজেই বিভিন্ন ধরনের কার্যক্রম করা যায়।
Enumerable মডিউল
Enumerable মডিউলটি ফাংশনাল প্রোগ্রামিংয়ের ধারণা অনুসরণ করে এবং এতে অনেক দরকারি মেথড অন্তর্ভুক্ত থাকে যা আপনার ডেটা সঞ্চয়গুলোর উপর কার্যক্রম করতে সহায়তা করে।
যতগুলো মেথড Enumerable মডিউলে সংজ্ঞায়িত থাকে, সেগুলো অধিকাংশ ক্ষেত্রে একটি block নেয় এবং collection এর প্রতিটি উপাদানের উপর প্রয়োগ করা হয়।
Enumerable মডিউল ব্যবহার
রুবির Enumerable মডিউল ব্যবহার করতে, ক্লাসে মডিউলটি ইনক্লুড করতে হবে। এটি সাধারণত ক্লাসের মধ্যে ডেটা ইটারেট করার জন্য স্বয়ংক্রিয়ভাবে কাজ করে। যেমন, Array এবং Hash ক্লাসগুলি এই মডিউলটি ইনক্লুড করে থাকে।
সিনট্যাক্স:
class MyClass
include Enumerable
endযেহেতু রুবির অধিকাংশ ডেটা স্ট্রাকচার (যেমন Array, Hash) ইতিমধ্যেই এই মডিউলটি ইনক্লুড করে থাকে, তাদের উপর সরাসরি Enumerable মেথড ব্যবহার করা যায়।
Common Methods in Enumerable
Enumerable মডিউল অনেক ধরনের মেথড সরবরাহ করে। নিচে কিছু গুরুত্বপূর্ণ এবং সাধারণভাবে ব্যবহৃত মেথডের আলোচনা করা হলো:
১. each
each মেথডটি একটি ব্লক গ্রহণ করে এবং কালেকশনের প্রতিটি উপাদানকে একে একে প্রক্রিয়া করে।
উদাহরণ:
[1, 2, 3].each do |number|
puts number * 2
endআউটপুট:
2
4
6এখানে, each ব্লককে প্রতি উপাদানের জন্য এক্সিকিউট করে।
২. map / collect
map বা collect মেথডটি প্রতিটি উপাদানকে প্রক্রিয়া করে এবং একটি নতুন অ্যারে রিটার্ন করে। এটি সাধারণত ট্রান্সফর্মেশন বা মান পরিবর্তন করতে ব্যবহৃত হয়।
উদাহরণ:
numbers = [1, 2, 3, 4]
squared_numbers = numbers.map { |number| number ** 2 }
puts squared_numbers # আউটপুট: [1, 4, 9, 16]এখানে, map মেথডটি প্রতি উপাদানকে স্কোয়ার করে নতুন অ্যারে তৈরি করেছে।
৩. select / filter
select (বা filter) মেথডটি একটি ব্লক নেয় এবং প্রতিটি উপাদান যাচাই করে, যেখানে true ফেরত দেওয়া উপাদানগুলো একটি নতুন অ্যারেতে সংগ্রহ করা হয়।
উদাহরণ:
numbers = [1, 2, 3, 4, 5]
even_numbers = numbers.select { |number| number.even? }
puts even_numbers # আউটপুট: [2, 4]এখানে, select মেথডটি কেবলমাত্র even (যোজ্য সংখ্যাগুলি) উপাদানগুলো নির্বাচন করেছে।
৪. reject
reject মেথডটি select এর বিপরীত কাজ করে। এটি ব্লকের ভিতরে false ফেরত দেয় এমন উপাদানগুলো ফিল্টার করে এবং একটি নতুন অ্যারে রিটার্ন করে।
উদাহরণ:
numbers = [1, 2, 3, 4, 5]
odd_numbers = numbers.reject { |number| number.even? }
puts odd_numbers # আউটপুট: [1, 3, 5]এখানে, reject মেথডটি শুধু odd (বিজোড়) সংখ্যাগুলোকে নির্বাচন করেছে।
৫. reduce / inject
reduce (বা inject) মেথডটি একটি একক মান তৈরির জন্য একটি অ্যারের উপাদানগুলিকে একত্রিত করে। এটি সাধারণত অ্যাকিউমুলেশন (যেমন যোগফল, গুণফল) করতে ব্যবহৃত হয়।
উদাহরণ:
numbers = [1, 2, 3, 4]
sum = numbers.reduce(0) { |accum, number| accum + number }
puts sum # আউটপুট: 10এখানে, reduce মেথডটি অ্যারের সব উপাদানকে একত্রিত করে তাদের যোগফল বের করেছে।
৬. all? / any?
all?: যদি সব উপাদান একটি নির্দিষ্ট শর্ত পূর্ণ করে, তবেtrueরিটার্ন করবে।any?: যদি কোনো একটি উপাদান শর্ত পূর্ণ করে, তবেtrueরিটার্ন করবে।
উদাহরণ:
numbers = [2, 4, 6]
puts numbers.all? { |number| number.even? } # আউটপুট: true
numbers = [2, 4, 7]
puts numbers.any? { |number| number.odd? } # আউটপুট: trueএখানে, all? সব উপাদানকে চেক করেছে যে তারা সব ইভেন কি না, এবং any? চেক করেছে যে কোনো উপাদান বিজোড় কি না।
Conclusion
- Enumerable মডিউল হল একটি রুবি মডিউল যা ইটারেশন, ফিল্টারিং, ম্যাপিং, অ্যাকিউমুলেশন ইত্যাদি অনেক কার্যক্রমের জন্য ব্যবহার করা যায়।
- রুবির অনেক ডেটা স্ট্রাকচার (যেমন Array, Hash, Range) এই মডিউলটি ইনক্লুড করে থাকে, যা তাদের উপর বিভিন্ন উচ্চ স্তরের কার্যক্রম পরিচালনা করতে সহায়তা করে।
map,select,reduce,eachইত্যাদি মেথডগুলি ডেটা ম্যানিপুলেশন এবং প্রোগ্রামিং কোডকে আরও সংক্ষিপ্ত ও কার্যকরী করতে ব্যবহৃত হয়।
এভাবে Enumerable মডিউল রুবি প্রোগ্রামিংয়ে কোড সহজ, পরিষ্কার এবং আরও কার্যকরী করতে সাহায্য করে।
Iterators রুবি প্রোগ্রামিং ভাষায় এমন একটি ফিচার যা দিয়ে আপনি collections (যেমন অ্যারে, হ্যাশ, রেঞ্জ) এর উপর লুপ চালাতে পারেন। Iterators বিভিন্ন ধরনের কাজ করতে ব্যবহৃত হয়, যেমন ডেটা পর্যালোচনা, পরিবর্তন, বা নির্বাচন। এগুলি রুবির একটি খুবই শক্তিশালী বৈশিষ্ট্য, যা কোডের কার্যকারিতা ও পাঠযোগ্যতা বৃদ্ধি করে।
রুবি প্রোগ্রামিংয়ে Iterators সাধারণত each, map, select, reject, reduce ইত্যাদি মেথড ব্যবহার করে ডেটা ম্যানিপুলেশন সম্পন্ন করা হয়।
১. each Iterator
each হল রুবির একটি খুব সাধারণ iterator, যা একটি অ্যারে বা হ্যাশের প্রতিটি উপাদান বা পেয়ার নিয়ে কাজ করতে ব্যবহৃত হয়। এই মেথডটি একটি ব্লক নেয় এবং ওই ব্লকটি প্রতিটি উপাদান নিয়ে একে একে কাজ করে।
Syntax:
collection.each do |item|
# ব্লক কোড যা প্রতিটি item নিয়ে কাজ করবে
endউদাহরণ:
# অ্যারে ডেটা
numbers = [1, 2, 3, 4, 5]
numbers.each do |num|
puts num * 2 # প্রতিটি সংখ্যাকে ২ দিয়ে গুণ করা হচ্ছে
endআউটপুট:
2
4
6
8
10এখানে, each ব্যবহার করে অ্যারের প্রতিটি উপাদানকে ডাবল করা হয়েছে।
২. map Iterator
map iterator ব্যবহার করে আপনি একটি নতুন অ্যারে তৈরি করতে পারেন, যা মূল অ্যারের প্রতিটি উপাদান নিয়ে ব্লকটি কার্যকর করে। এই iterator মূল অ্যারে পরিবর্তন না করে একটি নতুন অ্যারে রিটার্ন করে।
Syntax:
new_array = collection.map { |item| block_code }উদাহরণ:
# অ্যারে ডেটা
numbers = [1, 2, 3, 4, 5]
new_numbers = numbers.map { |num| num * 2 }
puts new_numbers.inspectআউটপুট:
[2, 4, 6, 8, 10]এখানে, map iterator মূল অ্যারের প্রতি উপাদানকে ২ দিয়ে গুণ করেছে এবং নতুন অ্যারে new_numbers তৈরি করেছে।
৩. select Iterator
select iterator ব্যবহার করে আপনি একটি ফিল্টারিং অপারেশন করতে পারেন। এটি একটি নতুন অ্যারে রিটার্ন করে, যা শুধুমাত্র সেই উপাদানগুলো নিয়ে থাকে যা ব্লকের শর্ত পূর্ণ করে।
Syntax:
new_array = collection.select { |item| block_condition }উদাহরণ:
# অ্যারে ডেটা
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
even_numbers = numbers.select { |num| num.even? }
puts even_numbers.inspectআউটপুট:
[2, 4, 6, 8]এখানে, select iterator ব্যবহার করে শুধুমাত্র জোড়া (even) সংখ্যাগুলিকে নির্বাচন করা হয়েছে।
৪. reject Iterator
reject iterator select এর বিপরীত কাজ করে। এটি একটি নতুন অ্যারে রিটার্ন করে, যা মূল অ্যারের সমস্ত উপাদান থেকে সেই উপাদানগুলো বাদ দিয়ে দেয়, যেগুলো ব্লকের শর্ত পূর্ণ করে।
Syntax:
new_array = collection.reject { |item| block_condition }উদাহরণ:
# অ্যারে ডেটা
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
odd_numbers = numbers.reject { |num| num.even? }
puts odd_numbers.inspectআউটপুট:
[1, 3, 5, 7, 9]এখানে, reject iterator ব্যবহার করে শুধু অজোড়া (odd) সংখ্যাগুলো রাখা হয়েছে।
৫. reduce Iterator
reduce (বা inject) iterator ব্যবহার করে আপনি একটি অ্যারের উপাদানগুলোর মধ্যে একটি একক মান তৈরির জন্য একটি সমন্বিত কার্যকলাপ সম্পন্ন করতে পারেন (যেমন যোগফল, গুণফল ইত্যাদি)।
Syntax:
result = collection.reduce(initial_value) { |accumulator, item| block_code }initial_value: এটি একটি প্রাথমিক মান যা প্রথমে অ্যাকুমুলেটর হিসাবে ব্যবহৃত হবে (যদি প্রয়োজন হয়)।accumulator: এটি একটি চলমান মান, যা প্রতিটি ব্লক কলের পর আপডেট হয়।item: এটি হচ্ছে প্রতিটি উপাদান।
উদাহরণ:
# অ্যারে ডেটা
numbers = [1, 2, 3, 4, 5]
sum = numbers.reduce(0) { |total, num| total + num }
puts sumআউটপুট:
15এখানে, reduce iterator অ্যারের সব সংখ্যার যোগফল বের করেছে। প্রথমে 0 মানটি অ্যাকুমুলেটর হিসেবে কাজ করেছে এবং পরে প্রতিটি সংখ্যার সাথে যোগফল করা হয়েছে।
৬. each_with_index Iterator
each_with_index iterator ব্যবহার করে আপনি প্রতিটি উপাদান এবং তার সাথে সম্পর্কিত ইনডেক্স (অথবা অবস্থান) একসাথে পেতে পারেন।
Syntax:
collection.each_with_index { |item, index| block_code }উদাহরণ:
# অ্যারে ডেটা
colors = ["red", "green", "blue", "yellow"]
colors.each_with_index do |color, index|
puts "Color ##{index + 1}: #{color}"
endআউটপুট:
Color #1: red
Color #2: green
Color #3: blue
Color #4: yellowএখানে, each_with_index iterator ব্যবহার করে প্রতিটি উপাদান এবং তার ইনডেক্স (অবস্থান) প্রদর্শিত হচ্ছে।
সারসংক্ষেপ
each: একটি অ্যারের প্রতিটি উপাদানের উপর লুপ চালায় এবং প্রতিটি উপাদান নিয়ে কোড কার্যকর করে।map: একটি নতুন অ্যারে তৈরি করে, যেখানে মূল অ্যারের প্রতিটি উপাদান নিয়ে কিছু পরিবর্তন করা হয়।select: নির্দিষ্ট শর্ত পূর্ণ করা উপাদানগুলো নির্বাচন করে একটি নতুন অ্যারে তৈরি করে।reject:selectএর বিপরীতে কাজ করে, শর্ত পূর্ণ করা উপাদানগুলো বাদ দিয়ে নতুন অ্যারে তৈরি করে।reduce: অ্যারের উপাদানগুলোর মধ্যে একটি একক মান (যেমন যোগফল) তৈরি করে।each_with_index: প্রতিটি উপাদান এবং তার ইনডেক্স (অবস্থান) নিয়ে কাজ করে।
এগুলি রুবি প্রোগ্রামিংয়ে ডেটা ম্যানিপুলেশন সহজ এবং কার্যকরী করতে সহায়তা করে। Iterators এর মাধ্যমে ডেটার উপর বিভিন্ন অপারেশন খুবই দ্রুত এবং ক্লিনভাবে সম্পন্ন করা যায়।
রুবি একটি ফাংশনাল প্রোগ্রামিং প্যারাডাইমের কিছু ধারণা সমর্থন করে, যেমন map, select, এবং reduce মেথড। এই মেথডগুলি কোলেকশন (যেমন অ্যারে বা হ্যাশ) নিয়ে কাজ করার জন্য ব্যবহৃত হয়, এবং এগুলি কোডকে আরও পরিষ্কার, সংক্ষিপ্ত এবং কার্যকরী করে তোলে। নিচে এই তিনটি মেথডের ব্যবহার বিস্তারিতভাবে আলোচনা করা হয়েছে।
১. map Method
map মেথড একটি কোলেকশনের প্রতিটি উপাদানকে ট্রান্সফর্ম (পরিবর্তন) করার জন্য ব্যবহৃত হয় এবং এর ফলস্বরূপ একটি নতুন কোলেকশন তৈরি করে, যেখানে প্রতিটি উপাদান নতুন মানে পরিবর্তিত হয়।
Syntax:
array.map { |element| # block code }এখানে, প্রতিটি উপাদান element হিসেবে মাপ করা হয় এবং ব্লক কোডের মাধ্যমে নতুন মান তৈরি হয়।
উদাহরণ:
numbers = [1, 2, 3, 4, 5]
squared_numbers = numbers.map { |num| num ** 2 }
puts squared_numbers # Output: [1, 4, 9, 16, 25]এখানে, map মেথডটি প্রতিটি সংখ্যাকে তার স্কয়ারে রূপান্তর করছে এবং নতুন অ্যারে squared_numbers তৈরি হচ্ছে।
আরেকটি উদাহরণ (স্ট্রিংয়ের সব অক্ষরকে বড় করা):
words = ["ruby", "rails", "developer"]
capitalized_words = words.map { |word| word.capitalize }
puts capitalized_words # Output: ["Ruby", "Rails", "Developer"]এখানে, map মেথডটি প্রতিটি স্ট্রিংয়ের প্রথম অক্ষরকে বড় করে নতুন অ্যারে তৈরি করছে।
২. select Method
select মেথড একটি কোলেকশনের মধ্যে থেকে নির্দিষ্ট শর্ত মেনে উপাদানগুলো ফিল্টার করে একটি নতুন কোলেকশন তৈরি করে। এটি শুধুমাত্র সেই উপাদানগুলো রাখে যেগুলি ব্লক শর্ত পূর্ণ করে।
Syntax:
array.select { |element| # condition }উদাহরণ:
numbers = [1, 2, 3, 4, 5, 6]
even_numbers = numbers.select { |num| num.even? }
puts even_numbers # Output: [2, 4, 6]এখানে, select মেথডটি শুধুমাত্র সেগুলিকে ফিরিয়ে দিয়েছে যেগুলি even (জোড়া সংখ্যা) ছিল।
আরেকটি উদাহরণ (বয়সের ভিত্তিতে নির্বাচন):
people = [
{ name: "Alice", age: 25 },
{ name: "Bob", age: 30 },
{ name: "Charlie", age: 17 },
{ name: "David", age: 22 }
]
adults = people.select { |person| person[:age] >= 18 }
puts adults.inspect # Output: [{:name=>"Alice", :age=>25}, {:name=>"Bob", :age=>30}, {:name=>"David", :age=>22}]এখানে, select মেথডটি মাত্র তাদের মানুষদের ফিরিয়ে দিয়েছে যাদের বয়স ১৮ বা তার বেশি।
৩. reduce Method
reduce (যাকে inject নামেও পরিচিত) একটি কোলেকশনের উপর একটি অ্যাকুমুলেটর (accumulator) প্রক্রিয়া চালানোর জন্য ব্যবহৃত হয়। এটি কোলেকশনের প্রতিটি উপাদানকে একটি একক মানে পরিণত করে (যেমন যোগফল, গুণফল ইত্যাদি)।
Syntax:
array.reduce(initial_value) { |accumulator, element| # block code }initial_value: অ্যাকুমুলেটরের শুরুর মান (এটি ঐচ্ছিক)।accumulator: এটি সঞ্চিত মান (এটি প্রথমেinitial_valueথেকে শুরু হয়)।element: এটি কোলেকশনের প্রতিটি উপাদান।
উদাহরণ:
numbers = [1, 2, 3, 4, 5]
sum = numbers.reduce(0) { |accumulator, num| accumulator + num }
puts sum # Output: 15এখানে, reduce মেথডটি অ্যারে numbers এর সমস্ত সংখ্যার যোগফল বের করছে, যেখানে 0 হচ্ছে initial_value (অ্যাকুমুলেটরের প্রাথমিক মান)। প্রতিটি উপাদানকে অ্যাকুমুলেটরের সাথে যোগ করা হয়েছে।
আরেকটি উদাহরণ (গুণফল বের করা):
numbers = [1, 2, 3, 4, 5]
product = numbers.reduce(1) { |accumulator, num| accumulator * num }
puts product # Output: 120এখানে, reduce মেথডটি সমস্ত সংখ্যার গুণফল বের করছে, যেখানে 1 হচ্ছে initial_value।
আরেকটি উদাহরণ (হাইস্ট ভ্যালু বের করা):
numbers = [1, 9, 3, 7, 5]
max_value = numbers.reduce { |accumulator, num| accumulator > num ? accumulator : num }
puts max_value # Output: 9এখানে, reduce মেথডটি অ্যারের মধ্যে সর্বোচ্চ মান (maximum value) বের করছে।
সারসংক্ষেপ
map: প্রতিটি উপাদানকে একটি নতুন মানে পরিবর্তন করে এবং একটি নতুন কোলেকশন রিটার্ন করে।select: কোলেকশন থেকে শর্ত পূর্ণ করা উপাদানগুলো নির্বাচন করে এবং একটি নতুন কোলেকশন তৈরি করে।reduce: কোলেকশনের সমস্ত উপাদানকে একত্রিত করে (যেমন যোগফল, গুণফল) একটি একক মানে রূপান্তর করে।
এই তিনটি মেথডই রুবিতে ফাংশনাল প্রোগ্রামিং কৌশল প্রয়োগে সহায়ক, এবং কোডকে আরও সংক্ষিপ্ত ও কার্যকরী করে তোলে।
Iterators হল প্রোগ্রামিংয়ের একটি কৌশল, যা একটি সংকলন (যেমন অ্যারে বা হ্যাশ) বা ডেটা স্ট্রাকচারের উপর একে একে প্রবাহিত হতে পারে। রুবি ভাষায় custom iterators তৈরি করা একটি গুরুত্বপূর্ণ দক্ষতা, যা ব্যবহারকারীর প্রয়োজন অনুযায়ী একটি ডেটা স্ট্রাকচারের উপর কাস্টম লজিক প্রয়োগ করতে সহায়তা করে।
রুবিতে custom iterators তৈরি করতে, আপনি সাধারণত each বা অন্য কোনো ইটারেটর মেথড ব্যবহার করেন, যার মাধ্যমে আপনি ক্লাস বা মডিউলে ডাইনামিকভাবে একটি ইটারেটর তৈরি করতে পারেন।
১. Custom Iterator তৈরি করা
রুবিতে একটি custom iterator তৈরি করতে, আপনি একটি মেথড ব্যবহার করতে পারেন যা একটি ব্লক গ্রহণ করবে এবং সেই ব্লকের উপর প্রতিটি উপাদান প্রয়োগ করবে। রুবি প্রোগ্রামে, yield ব্যবহারের মাধ্যমে আপনি একটি ব্লক কল করতে পারেন এবং এটি ইটারেটর হিসেবে কাজ করতে পারে।
উদাহরণ:
ধরা যাক, আপনি একটি ক্লাস তৈরি করছেন যা একটি অ্যারে ইটারেট করবে।
class MyArray
def initialize(arr)
@arr = arr
end
# Custom iterator
def my_each
for element in @arr
yield element # Calling the block with each element
end
end
end
my_array = MyArray.new([1, 2, 3, 4, 5])
my_array.my_each do |num|
puts num * 2 # Output: 2, 4, 6, 8, 10
endএখানে, my_each মেথড একটি কাস্টম ইটারেটর তৈরি করেছে, যা অ্যারের প্রতিটি উপাদানকে ব্লকটির মধ্যে পাঠায় এবং ব্লকের মধ্যে ডিফাইন করা লজিক (এখানে num * 2) প্রয়োগ হয়।
২. Custom Iterator with Additional Logic
আপনি চাইলে আপনার কাস্টম ইটারেটরে অতিরিক্ত লজিক যোগ করতে পারেন। উদাহরণস্বরূপ, আপনি ইটারেটরের মধ্যে একটি শর্ত যোগ করতে পারেন, যাতে কিছু উপাদান বাদ দেওয়া যায় বা ফিল্টার করা যায়।
উদাহরণ:
class MyArray
def initialize(arr)
@arr = arr
end
# Custom iterator with filtering logic
def my_each_with_condition
for element in @arr
if element.even? # Only yield even numbers
yield element
end
end
end
end
my_array = MyArray.new([1, 2, 3, 4, 5])
my_array.my_each_with_condition do |num|
puts num # Output: 2, 4
endএখানে, my_each_with_condition কাস্টম ইটারেটরটি শুধু even numbers (যতগুলো সংখ্যা ২ দিয়ে ভাগ করা যায়) ব্লকে পাঠায় এবং সেগুলোর উপর অপারেশন প্রয়োগ করে।
৩. Using Enumerator for Custom Iterators
রুবি Enumerator ক্লাসও ব্যবহার করে কাস্টম ইটারেটর তৈরি করা যায়। এটি আপনাকে একটি lazy ইটারেটর প্রদান করে, যার মাধ্যমে শুধুমাত্র প্রয়োজনীয় উপাদানগুলি একে একে গেনারেট হয় এবং মেমরি দক্ষতার সাথে কাজ করা যায়।
উদাহরণ:
class MyArray
def initialize(arr)
@arr = arr
end
# Custom iterator using Enumerator
def my_each
Enumerator.new do |yielder|
@arr.each { |item| yielder << item }
end
end
end
my_array = MyArray.new([1, 2, 3, 4, 5])
enum = my_array.my_each
enum.each { |num| puts num * 2 } # Output: 2, 4, 6, 8, 10এখানে, my_each মেথড একটি Enumerator তৈরি করে এবং yielder অবজেক্ট ব্যবহার করে প্রতিটি উপাদান ব্লকে পাঠানো হয়। এটি একটি ইটারেটর হিসেবে কাজ করে এবং একে একে ডেটার উপর অপারেশন করে।
৪. Custom Iterator with Multiple Blocks
রুবিতে একটি মেথড একাধিক ব্লক গ্রহণ করতে পারে না, তবে আপনি যদি একাধিক প্রক্রিয়া একে একে চালাতে চান, তবে একাধিক ব্লকগুলি একসাথে নেয়ার জন্য proc বা lambda ব্যবহার করতে পারেন।
উদাহরণ:
class MyArray
def initialize(arr)
@arr = arr
end
# Custom iterator with two blocks
def my_each_with_two_blocks(proc1, proc2)
@arr.each do |element|
proc1.call(element)
proc2.call(element)
end
end
end
my_array = MyArray.new([1, 2, 3, 4, 5])
proc1 = Proc.new { |num| puts num * 2 } # Multiply by 2
proc2 = Proc.new { |num| puts num + 1 } # Add 1
my_array.my_each_with_two_blocks(proc1, proc2)
# Output:
# 2
# 2
# 4
# 3
# 6
# 4
# 8
# 5
# 10
# 6এখানে, দুটি আলাদা Proc তৈরি করা হয়েছে এবং my_each_with_two_blocks মেথডে দুটি ব্লক একে একে কল করা হচ্ছে।
৫. Advantages of Custom Iterators
- Code Reusability: একবার তৈরি করা হলে, কাস্টম ইটারেটর অন্যান্য কোডে পুনঃব্যবহারযোগ্য হয়, যেটি কোডের পুনঃব্যবহারযোগ্যতা বাড়ায়।
- Abstraction: কাস্টম ইটারেটর ডেটার উপর কাজ করার একটি সাধারণ পদ্ধতি তৈরি করে, যা কোডের অ্যাবস্ট্রাকশন উন্নত করে।
- Flexibility: আপনার কোডের মধ্যে dynamic behavior যোগ করতে, যেমন শর্ত বা ফিল্টারিং লজিক, যা সাধারণ ইটারেটর ব্যবহার করে সম্ভব নয়।
- Memory Efficiency: Enumerator ব্যবহার করে আপনি একটি lazy evaluation মেথড তৈরি করতে পারেন, যা শুধুমাত্র প্রয়োজনীয় উপাদানগুলো একে একে প্রসেস করে।
সারসংক্ষেপ
- Custom Iterators রুবিতে এমন একটি কৌশল যা ডেটার উপর dynamic behavior প্রয়োগ করতে সক্ষম করে এবং কোডের নমনীয়তা এবং পুনঃব্যবহারযোগ্যতা নিশ্চিত করে।
each,define_method,ProcএবংEnumeratorব্যবহার করে আপনি কাস্টম ইটারেটর তৈরি করতে পারেন।- কাস্টম ইটারেটরের মাধ্যমে আপনি filtering, sorting, mapping এবং accumulation এর মতো নানা ধরনের কাজ করতে পারেন।
এটি আপনার প্রোগ্রামিংয়ের দক্ষতা বাড়াতে সহায়ক হতে পারে এবং ডেটা ম্যানিপুলেশনকে আরও কার্যকর ও নমনীয় করে তোলে।
Read more