কম্পিউটার

রুবির জাদুকরী গণনাযোগ্য মডিউল

রুবি ম্যাজিকের আরেকটি পর্বের সময় এসেছে! এই সময়, আমরা রুবির সবচেয়ে জাদুকরী বৈশিষ্ট্যগুলির মধ্যে একটি দেখব, যেটি 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 প্রয়োগ করব একটি লিঙ্ক করা তালিকাতে এটিকে গণনাযোগ্য করতে।

লিঙ্ক করা তালিকা:অ্যারে ছাড়া তালিকা

একটি লিঙ্ক করা তালিকা হল ডেটা উপাদানগুলির একটি সংগ্রহ, যেখানে প্রতিটি উপাদান পরের দিকে নির্দেশ করে। তালিকার প্রতিটি উপাদানের দুটি মান রয়েছে, যার নাম head এবং লেজ . মাথাটি উপাদানটির মান ধরে রাখে এবং লেজটি তালিকার বাকি অংশের একটি লিঙ্ক৷

[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 ফেরত দিতে হবে উদাহরণ যখন আমাদের #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. রুবিতে বিটওয়াইজ হ্যাক

  2. রুবিতে ল্যাম্বডাস ব্যবহার করা

  3. রুবি 2.6-এ 9টি নতুন বৈশিষ্ট্য

  4. রুবি গণনাযোগ্য মডিউলের একটি প্রাথমিক নির্দেশিকা (+ আমার প্রিয় পদ্ধতি)