কম্পিউটার টিউটোরিয়াল

Swift মাস্টার করুন: Map, Filter, এবং Reduce ফাংশনের ভেতরে ঝাঁকুন

একটি ফাংশন কিছু ইনপুট নেয়, সেটির সাথে কিছু করে, এবং একটি আউটপুট তৈরি করে। একটি ফাংশনের একটি সিগনেচার এবং একটি বডি থাকে। আপনি যদি একই ইনপুট একটি ফাংশনে দেন, তবে আপনি সবসময় একই আউটপুট পাবেন। সংক্ষেপে এটি ফাংশন-এর একটি ডেফিনিশন।

এখন আমরা ফাংশন সম্পর্কে আরও জানব সেগুলোর ভেতরে ঘুসে। আমরা Swift-এ হायर-অর্ডার ফাংশন এক্সপ্লোর করব। একটি ফাংশন যা অন্য একটি ফাংশন ইনপুট হিসেবে নেয় বা একটি ফাংশন রিটার্ন করে তাকে একটি হायर-অর্ডার ফাংশন বলা হয়।

Swift-এ, আমরা map, filter, reduce প্রতিদিন নিয়ে খেলি। যখন আমরা এই ফাংশনগুলো ব্যবহার করি, তবে এটা যেন ম্যাজিক লাগে। এই পয়েন্টে, আপনার পেছনের দৃশ্যে কী হচ্ছে সেটা বুঝতে পারেন না। Map, Filter, এবং Reduce ফাংশনাল প্রোগ্রামিংয়ের আইডিয়া এবং পদ্ধতির মাধ্যমে কাজ করে। যদিও Swift একটি পিউর ফাংশনাল ল্যাঙ্গুয়েজ নয়, এটি আপনাকে ফাংশনাল জিনিসগুলো করতে দেয়।

এখন একে একে দেখি পেছনের দৃশ্যে তাদের জন্য কী হচ্ছে। প্রথমে আমরা এই ফাংশনগুলোর বেসিক ভার্সন কিছু নির্দিষ্ট ডেটা টাইপের জন্য বাস্তবায়ন করব, তারপর একটি জেনেরিক ভার্সন বাস্তবায়ন করার চেষ্টা করব।

Map ফাংশন

ধরুন আমাদের একটি ইন্টিজার অ্যারে আছে এবং আমাদের একটি ফাংশন লিখতে হবে যা অরিজিনাল অ্যারের প্রতিটি এলিমেন্টে কিছু ডেল্টা ভ্যালু যোগ করে একটি নতুন অ্যারে রিটার্ন করে। আমরা সহজে একটি ফর লুপ ব্যবহার করে এই ফাংশন লিখতে পারি নিচের মত করে:

আমাদের এখন আরেকটি ফাংশন দরকার যা অরিজিনাল অ্যারের প্রতিটি এলিমেন্ট ডাবল করে একটি নতুন অ্যারে রিটার্ন করবে। এর জন্য, আমরা নিচের মত বাস্তবায়ন করতে পারি:

আমরা উপরের দুটি ফাংশনকে ভালোভাবে নজর করলে দেখতে পাব যে তারা মূলত একই কাজ করছে। শুধু ফর লুপের ভিতরের ফাংশনালিটি ভিন্ন। উভয়ই একটি Integer অ্যারে ইনপুট হিসেবে নেয়, ফর লুপ ব্যবহার করে প্রতিটি এলিমেন্ট ট্রান্সফর্ম করে, এবং একটি নতুন অ্যারে রিটার্ন করে। তাই মূল কথা হলো প্রতিটি এলিমেন্টকে কিছু নতুনতে ট্রান্সফর্ম করা।

যেহেতু Swift হायर-অর্ডার ফাংশন সাপোর্ট করে, আমরা একটি ফাংশন লিখতে পারি যা একটি ইন্টিজার অ্যারে নেবে, একটি ট্রান্সফর্ম ফাংশন ইনপুট হিসেবে নেবে, এবং অরিজিনাল অ্যারের প্রতিটি এলিমেন্টে ট্রান্সফর্ম ফাংশন প্রয়োগ করে একটি নতুন অ্যারে রিটার্ন করবে।

কিন্তু এখনও উপরের সাথে একটি সমস্যা আছে: এটি শুধু ইন্টিজার অ্যারে রিটার্ন করে। আপনার যদি ইনপুট ইন্টিজার অ্যারেকে স্ট্রিং অ্যারেতে কনভার্ট করার রিকোয়ারমেন্ট থাকে, তবে এই ফাংশন দিয়ে সেটা করা যাবে না। সেটা করার জন্য, আমাদের একটি জেনেরিক ফাংশন লিখতে হবে যেটা যেকোনো টাইপের জন্য কাজ করবে।

আমরা একটি Array এক্সটেনশনে জেনেরিক ফাংশন এইভাবে বাস্তবায়ন করতে পারি:

  1. Array Extension-এ একটি map ফাংশন ডিক্লেয়ার করুন যা জেনেরিক টাইপ T দিয়ে কাজ করে।
  2. ফাংশনটি (Element) ->; T টাইপের একটি ফাংশন ইনপুট হিসেবে নেয়
  3. ফাংশনের ভিতরে একটি খালি রেজাল্ট অ্যারে ডিক্লেয়ার করুন যা T টাইপের ডেটা ধারণ করবে।
  4. একটি ফর লুপ বাস্তবায়ন করুন যা নিজের ওপর ইটারেট করবে এবং ট্রান্সফর্ম ফাংশন কল করে এলিমেন্টকে টাইপ T-এ কনভার্ট করবে
  5. কনভার্ট করা ভ্যালু রেজাল্টিং অ্যারেতে অ্যাপেন্ড করুন

এইভাবে Swift-এ map ফাংশন কাজ করে। আমাদের যদি map function, বাস্তবায়ন করতে হয়, তবে আমরা উপরের মত বাস্তবায়ন করতাম। তাই মূলত, এটি একটি অ্যারেতে কোনো ম্যাজিক করে না — আমরা সহজে নিজেরাই ফাংশনটি ডিফাইন করতে পারতাম।

Filter ফাংশন

ধরুন আমাদের একটি ইন্টিজার অ্যারে আছে এবং আমরা শুধু ইভেন নাম্বারগুলো অ্যারেতে রাখতে চাই। আমরা একটি সিম্পল ফর লুপ ব্যবহার করে এটি বাস্তবায়ন করতে পারি:

আবার বলুন, আমাদের একটি স্ট্রিং অ্যারে আছে যেটা একটি প্রজেক্টের ক্লাস ফাইল নাম রিপ্রেজেন্ট করে এবং আমরা শুধু .swift ফাইলগুলো রাখতে চাই। এটি একটি সিঙ্গেল লুপ দিয়ে করা যায় নিচের মত করে:

আমরা উপরের দুটি ফাংশন বাস্তবায়নকে ঘনিষ্ঠভাবে দেখলে বুঝতে পারি যে তারা মূলত একই কাজ করছে — শুধু দুটি অ্যারের ডেটা টাইপ ভিন্ন। আমরা এটি জেনেরালাইজ করতে পারি একটি জেনেরিক filter ফাংশন বাস্তবায়ন করে, যা একটি অ্যারে এবং একটি ফাংশন ইনপুট হিসেবে নেয়, এবং includeElement ফাংশনের আউটপুটের ওপর নির্ভর করে রেজাল্টিং অ্যারেতে এলিমেন্ট যোগ করতে হবে কিনা সেটা ডিসাইড করে।

Reduce ফাংশন

ধরুন আমাদের একটি ইন্টিজার অ্যারে আছে এবং আমরা দুটি ফাংশন বাস্তবায়ন করতে চাই যা এলিমেন্টগুলোর যোগফল এবং গুণফল রিটার্ন করবে। আমরা একটি সিম্পল ফর লুপ ব্যবহার করে এটি বাস্তবায়ন করতে পারি:

এখন ইন্টিজার অ্যারের বদলে, ধরুন আমাদের একটি স্ট্রিং অ্যারে আছে এবং আমরা অ্যারের সকল এলিমেন্ট কনক্যাটেনেট করতে চাই:

উপরের তিনটি ফাংশন মূলত একই কাজ করছে। তারা একটি অ্যারে ইনপুট হিসেবে নেয়, একটি রেজাল্টিং ভেরিয়েবল ইনিশিয়ালাইজ করে, অ্যারেতে ইটারেট করে, এবং রেজাল্টিং ভেরিয়েবল আপডেট করে।

এখান থেকে আমরা একটি জেনেরিক ফাংশন বাস্তবায়ন করতে পারি যা সকল টাইপের জন্য কাজ করবে। এর জন্য আমাদের রেজাল্টিং ভেরিয়েবলের ইনিশিয়াল ভ্যালু এবং সেই ভেরিয়েবল আপডেট করার ফাংশন প্রতিটি ইটারেশনে দরকার।

তাই আমরা জেনেরিক ফাংশন নিচের ডেফিনিশন দিয়ে বাস্তবায়ন করতে পারি:

উপরের বাস্তবায়ন যেকোনো ইনপুট অ্যারে টাইপ [Element]. এর জন্য জেনেরিক। এটি T টাইপের একটি রেজাল্ট কম্পিউট করবে। কাজ করার জন্য, এটাকে T টাইপের একটি ইনিশিয়াল ভ্যালু দরকার রেজাল্টিং ভেরিয়েবলে অ্যাসাইন করার জন্য। তারপর, এটি (T, Element) -> T টাইপের একটি ফাংশন দরকার যেটা ফর লুপের প্রতিটি ইটারেশনে রেজাল্টিং ভেরিয়েবল আপডেট করতে ব্যবহার হবে।

পড়ার জন্য ধন্যবাদ!

  1. জাভাস্ক্রিপ্টে ফাংশন ও মেথডের পার্থক্য

  2. মাদারবোর্ড বোঝা: ফাংশন ও সংজ্ঞা

  3. Swift-এ ফাংশন কম্পোজিশনে পারদর্শী হন: সংক্ষিপ্ত গাইড

  4. Swift-এ Generics বনাম Any: মূল পার্থক্য এবং সেরা প্র্যাকটিস