Lesson ১৪৬ মিনিট পড়া

ল্যাম্বডা, ম্যাপ এবং ফিল্টার (Lambda, Map & Filter)

ছোট্ট কিন্তু শক্তিশালী ফাংশন যা ব্যবহারের পর ফেলে দেওয়া যায়

ল্যাম্বডা ফাংশন — এক লাইনের বিস্ময় (Lambda Functions — One-Line Wonders)

ল্যাম্বডা (lambda) হলো একটি মিনি ফাংশন যা এতই ছোট যে এর কোনো নাম দেওয়ার প্রয়োজন হয় না। এটিকে একটি স্টিকি নোট বা ছোট চিরকুটের সাথে তুলনা করতে পারেন যেটিতে দ্রুত কিছু নির্দেশ লেখা থাকে: "এই সংখ্যাটিকে দ্বিগুণ করো" বা "এটি কি জোড় সংখ্যা?"। আপনি এটি একবার ব্যবহার করেন এবং তারপর ফেলে দেন।

এর লেখার নিয়ম বা সিনট্যাক্স হলো: lambda parameters: expression

মূল নিয়মসমূহ:

  • শুধুমাত্র একটি এক্সপ্রেশন (expression) থাকবে — কোনো স্টেটমেন্ট, if/for ব্লক, বা অ্যাসাইনমেন্ট থাকবে না।
  • এটি স্বয়ংক্রিয়ভাবে সেই এক্সপ্রেশনের রেসাল্ট বা ফলাফলটি রিটার্ন করে (কোনো return কীওয়ার্ডের প্রয়োজন হয় না)।
  • sorted(), map(), এবং filter() এর মতো ফাংশনগুলোতে দ্রুত একটি আর্গুমেন্ট হিসেবে ব্যবহার করার জন্য এটি সবচেয়ে ভালো।

ল্যাম্বডা এর বেসিকস (Lambda Basics)

# Regular function
def double(x):
return x * 2
# Same thing as a lambda
double_lambda = lambda x: x * 2
print(double(5)) # 10
print(double_lambda(5)) # 10
# Lambda with multiple parameters
add = lambda a, b: a + b
print(add(3, 7)) # 10
# Lambda with a conditional expression
category = lambda age: "adult" if age >= 18 else "minor"
print(category(25)) # adult
print(category(12)) # minor
# Most useful: inline with sorted()
students = [("Anika", 92), ("Rafi", 85), ("Sadia", 97)]
by_score = sorted(students, key=lambda s: s[1], reverse=True)
print(by_score)
Output
10
10
10
adult
minor
[('Sadia', 97), ('Anika', 92), ('Rafi', 85)]

map() — প্রতিটি উপাদানে পরিবর্তন আনুন (map() — Transform Every Item)

map() একটি ফাংশন গ্রহণ করে এবং এটিকে কোনো ইটারেবলের (iterable) প্রতিটি উপাদানে বা আইটেমে প্রয়োগ করে, অনেকটা প্রতিটি জিনিসকে কোনো মেশিনের ভেতর দিয়ে পাঠানোর মতো। এটি একটি ম্যাপ অবজেক্ট (লেজি বা lazy) রিটার্ন করে, তাই এর ফলাফল বা রেসাল্ট দেখতে এটিকে list() দিয়ে মুড়িয়ে দিন।

প্যাটার্ন: map(function, iterable)

এটি মূলত লিস্ট কম্প্রিহেনশনের (list comprehensions) একটি ফাংশনাল প্রোগ্রামিং বিকল্প। কাজের ধরনের ওপর ভিত্তি করে যেটি পড়তে বেশি সহজ মনে হয়, সেটিই ব্যবহার করুন।

map() এর ব্যবহার (map() in Action)

# Square every number
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x ** 2, numbers))
print("Squared:", squared)
# Convert strings to integers
str_numbers = ["10", "20", "30", "40"]
int_numbers = list(map(int, str_numbers)) # Built-in function as argument!
print("Integers:", int_numbers)
# Temperature conversion: Celsius → Fahrenheit
celsius = [0, 20, 37, 100]
fahrenheit = list(map(lambda c: round(c * 9/5 + 32, 1), celsius))
print("Fahrenheit:", fahrenheit)
# map with multiple iterables
names = ["anika", "rafi", "sadia"]
greetings = ["hi", "hello", "hey"]
result = list(map(lambda g, n: f"{g.title()}, {n.title()}!", greetings, names))
print(result)
Output
Squared: [1, 4, 9, 16, 25]
Integers: [10, 20, 30, 40]
Fahrenheit: [32.0, 68.0, 98.6, 212.0]
['Hi, Anika!', 'Hello, Rafi!', 'Hey, Sadia!']

filter() — যা শর্ত পূরণ করে কেবল তা-ই রাখুন (filter() — Keep Only What Passes)

filter() অনেকটা অফিসের বা ব্যাংকের দারোয়ানের মতো — এটি প্রতিটি আইটেমকে একটি শর্তের ওপর ভিত্তি করে যাচাই করে এবং কেবল সেগুলোকেই ভেতরে ঢুকতে দেয় যেগুলোর ফলাফল True হয়।

প্যাটার্ন: filter(function, iterable)

ফাংশনটিকে প্রতিটি আইটেমের জন্য True (রাখবে) অথবা False (বাতিল করবে) রিটার্ন করতে হবে।

filter() এবং reduce() (filter() and reduce())

# Filter even numbers
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
evens = list(filter(lambda x: x % 2 == 0, numbers))
print("Evens:", evens)
# Filter non-empty strings
words = ["", "hello", "", "world", " ", "python"]
non_empty = list(filter(lambda w: w.strip(), words))
print("Non-empty:", non_empty)
# Filter passing scores
scores = {"Anika": 92, "Rafi": 58, "Sadia": 74, "Tariq": 45, "Esha": 88}
passing = dict(filter(lambda item: item[1] >= 60, scores.items()))
print("Passing:", passing)
# reduce() — combine all items into one value
from functools import reduce
nums = [1, 2, 3, 4, 5]
product = reduce(lambda a, b: a * b, nums)
print(f"\nProduct of {nums}: {product}") # 1*2*3*4*5 = 120
# reduce to find longest word
words = ["cat", "elephant", "dog", "hippopotamus", "ant"]
longest = reduce(lambda a, b: a if len(a) > len(b) else b, words)
print(f"Longest word: {longest}")
Output
Evens: [2, 4, 6, 8, 10]
Non-empty: ['hello', 'world', 'python']
Passing: {'Anika': 92, 'Sadia': 74, 'Esha': 88}

Product of [1, 2, 3, 4, 5]: 120
Longest word: hippopotamus

sorted() এর সাথে key — নিজের মতো করে সাজানো (sorted() with key — Custom Sorting)

sorted() এর key প্যারামিটারটি হলো সেই জায়গা যেখানে ল্যাম্বডার সবচেয়ে ভালো কাজ দেখা যায়। আপনি এটিকে এমন একটি ফাংশন দেন যা প্রতিটি আইটেম থেকে "সাজানোর মান (sort value)" বের করে আনে। পাইথন এই বের করা মানগুলো ব্যবহার করেই তাদের ক্রম বা অর্ডার (order) নির্ধারণ করে।

key এর সাহায্যে কাস্টম সর্টিং (Custom Sorting with key)

# Sort strings by length
fruits = ["জাম", "kiwi", "strawberry", "fig", "আম"]
by_length = sorted(fruits, key=lambda f: len(f))
print("By length:", by_length)
# Sort dicts by a specific field
students = [
{"name": "Anika", "gpa": 3.8},
{"name": "Rafi", "gpa": 3.2},
{"name": "Sadia", "gpa": 3.9},
{"name": "Tariq", "gpa": 3.5},
]
honor_roll = sorted(students, key=lambda s: s["gpa"], reverse=True)
for s in honor_roll:
print(f" {s['name']}: {s['gpa']}")
# Sort by multiple criteria (GPA desc, then name asc)
students.append({"name": "Esha", "gpa": 3.8})
multi_sort = sorted(students, key=lambda s: (-s["gpa"], s["name"]))
print("\nMulti-sort:")
for s in multi_sort:
print(f" {s['name']}: {s['gpa']}")
Output
By length: ['fig', 'kiwi', 'আম', 'জাম', 'strawberry']
  Sadia: 3.9
  Anika: 3.8
  Tariq: 3.5
  Rafi: 3.2

Multi-sort:
  Sadia: 3.9
  Anika: 3.8
  Esha: 3.8
  Tariq: 3.5
  Rafi: 3.2
Note: ল্যাম্বডা নাকি কম্প্রিহেনশন? সাধারণ পরিবর্তনের (transforms) জন্য list(map(lambda x: x**2, nums)) এর চেয়ে [x**2 for x in nums] পড়া সাধারণত বেশি সহজ। কিন্তু যখন আপনি sorted(key=...) তে কোনো ফাংশন পাস করছেন বা কোনো কলব্যাক ব্যবহার করছেন, তখন ল্যাম্বডাই হলো একদম সঠিক টুল।
চ্যালেঞ্জ

ছোট কুইজ

lambda x, y: x + y কী তৈরি করে?
Modules & ImportsDecorators & Closures