সেট #
ক্লাস নাইন-টেনের সেই দিনগুলি কি মনে আছে আমাদের? বিশেষ করে সাধারণ গণিত বইটার কথা? ১.১ আর ১.২ এর কথা ভুলতে পেরেছি কেউ? নাহ, সেটের সাথে সেই প্রথম পরিচয়ের কথা ভোলা সম্ভব না। আসলে, প্রথম পরিচয় আর প্রথম স্পর্শ কখনো ভোলা যায় না। কি শিখেছিলাম সেই সেট অধ্যায়ে?
গাণিতিক সেট #
এখন কিছুক্ষণ গণিত শেখা যাক। গাণিতিক সেট হচ্ছে সুনির্দিষ্টভাবে সংজ্ঞায়িত বস্তুসমূহের সমাহার। সেটের অন্তর্গত প্রত্যেক বস্তুকে ঐ সেটের উপাদান বা সদস্য বলা হয়। এই সদস্য অবশ্যই সুনির্দিষ্টভাবে সংজ্ঞায়িত হবে আর একটা সেটে একই সদস্য দুইবার থাকতে পারবে না। সেট দুই পদ্ধতিতে প্রকাশ করা যায়:
- তালিকা পদ্ধতি, যেমন: A = {1, 2, 3, 4, 5}
- সেট গঠন পদ্ধতি
পাইথনে সেট নিয়ে আলোচনার জন্য তালিকা পদ্ধতিটা কাজে আসবে আমাদের।
পাইথনে সেট #
পাইথনে সেট হল একটা ডাটা টাইপ, অনেকটা লিস্টের মতই। লিস্টের সাথে সেটের পার্থক্য হল, লিস্টে একই আইটেম একাধিকবার থাকতে পারবে কিন্তু সেটে একটা সদস্য বা আইটেম কেবল ও কেবলমাত্র একবারই থাকবে। সবচেয়ে মজার ব্যাপার হল, গণিতে আমরা সেটের যেসব অপারেশন করতাম (যেমন: ইউনিয়ন, ইন্টারসেকশন, ডিফারেন্স) তার সবই পাইথনে করা যায়।
পাইথনে সেট তৈরি করার জন্য আমরা {}
চিহ্ন বা set()
ফাংশন ব্যবহার করতে পারি। তবে অসুবিধার কথা হল set()
ফাংশন দিয়ে ফঁকা সেট তৈরি করা গেলেও {}
চিহ্ন দিয়া ফাঁকা সেট তৈরি করা যায় না। এই চিহ্নটা ফাঁকা ডিকশনারি তৈরি করে। একটা উদাহরণ দেখা যাক:
>>> A = {'orange', 'banana', 'pear', 'apple'}
>>> A
{'apple', 'banana', 'pear', 'orange'}
>>> type(A)
<class 'set'>
>>> A = set('orange', 'banana', 'pear', 'apple')
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
A = set('orange', 'banana', 'pear', 'apple')
TypeError: set expected at most 1 arguments, got 4
>>> A = set('abracadabra')
>>> A
{'b', 'r', 'c', 'a', 'd'}
>>> type(A)
<class 'set'>
প্রথম স্টেটমেন্টে {}
চিহ্ন দিয়ে আমরা একটা সেট ভ্যারিয়েবল A তৈরি করেছি। তৃতীয় স্টেটমেন্টে আমরা A ভ্যারিয়েবলের টাইপ চেক করে দেখেছি। চতুর্থ স্টেটমেন্টে set()
ফাংশন দিয়ে আমরা একটা সেট তৈরি করতে চেষ্টা করেছি। কিন্তু পাইথন TypeError
থ্রো করেছে। কারণ আমরা সেট ফাংশনের ভিতর কেবল ও কেবলমাত্র একটা জিনিস দিতে পারব। পঞ্চম স্টেটমেন্টে আমরা সেট ফাংশনের ভিতর একটা স্ট্রিং দিয়েছি। ষষ্ঠ স্টেটমেন্টে দেখতে পাচ্ছি, ঐ স্ট্রিংয়ের প্রতিটা ক্যারেক্টারকে মাত্র একবার করে নিয়ে একটা সেট গঠিত হয়েছে। আমরা কিন্তু আগেই জেনেছি, সেটে একটি আইটেম বা উপাদান মাত্র একবারই থাকবে। একটা উদাহরণ দেখা যাক:
>>> A = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
>>> A
{'banana', 'apple', 'pear', 'orange'}
আমরা ‘apple’ আর ‘orange’ কে দুইবার করে দিলেও সেটের ভিতর তারা একবার করে আছে। এবার ফাঁকা সেটের ব্যাপারটা দেখা যাক:
>>> A = set()
>>> type(A)
<class 'set'>
>>> A
set()
>>> A = {}
>>> A
{}
>>> type(A)
<class 'dict'
হুম, {}
চিহ্ন দিয়ে কোন ফাঁকা সেট তৈরি করা যায় না। তাহলে ফাঁকা সেটের জন্য set()
ফাংশনই ইউজ করতে হবে। একটা কথা বলতে ভুলে গেছি, এই যে সেট ফাংশনের কথা বলছি এটা কিন্তু আসলে একটা ক্লাস। তবে যেহেতু আমরা এখন অবধি ক্লাস চিনি না তাই আমরা একে মেশিন বা ফাংশনই বলব।
অ্যাক্সেস আইটেম #
এবার আমরা সেটের উপাদান বা ভ্যালুগুলো অ্যাক্সেস করব।
>>> A = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
>>> A
{'pear', 'apple', 'orange', 'banana'}
>>> A[0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'set' object does not support indexing
খাইছে! পাইথন তো TypeError
থ্রো করেছে। আসলে, সেটের উপাদানগুলোকে ইনডেক্স নম্বর দিয়ে অ্যাক্সেস করা যায় না।
উপাদান করি যোগ #
আমরা চাইলে সেটে নতুন একটা উপাদান বা এলিমেন্ট যোগ করতে পারি। এজন্য আমাদেরকে add()
ফাংশন ব্যবহার করতে হবে। এই ফাংশনের ভিতর আমরা যে উপাদান দেব তাই সেটে যোগ হয়ে যাবে।
>>> A = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
>>> A
{'apple', 'orange', 'banana', 'pear'}
>>> A.add('pineapple')
>>> A
{'apple', 'orange', 'banana', 'pear', 'pineapple'}
আর যদি একই সাথে কয়েকটা উপাদান যোগ করতে চাই তখন কিন্তু add()
ফাংশন দিয়ে কাজ হবে না। তখন আমাদের update()
ফাংশন ব্যবহার করতে হবে। এই ফাংশনের ভিতর মাল্টিপল ভ্যালু দিলেই তা অ্যাড হয়ে যাবে।
>>> A
{'apple', 'orange', 'banana', 'pear', 'pineapple'}
>>> A.update('berry', 'grape')
>>> A
{'r', 'apple', 'pineapple', 'b', 'orange', 'banana', 'y', 'g', 'a', 'p', 'e', 'pear'}
>>> A.update({'berry', 'grape'})
>>> A
{'r', 'apple', 'pineapple', 'b', 'orange', 'banana', 'y', 'g', 'a', 'p', 'berry', 'grape', 'e', 'pear'}
আমরা একবার নরমালি দুইটা এলিমেন্ট পাস করেছিলাম। কিন্তু তখন জিনিসগুলা ক্যারেক্টার হিসাবে ভাগ হয়ে সেটে অ্যাড হয়েছে। আমরা যেভাবে দিয়েছি সেভাবে অ্যাড করার জন্য এলিমেন্টগুলোকে {}
চিহ্নের ভিতরে পুরে পাঠাতে হবে।
উপাদান দিলাম খাইয়া #
ধরা যাক, A সেট থেকে আমরা একটা এলিমেন্টকে খাইয়া দিতে চাই মানে রিমুভ করতে চাই। সেক্ষেত্রে আমাদেরকে remove()
ফাংশনটা ব্যবহার করতে হবে। এই ফাংশনের ভিতর যা দেব সেটা যদি সেটে থেকে থাকে তবে রিমুভ হয়ে যাবে। আর না থাকলে KeyError
এরর থ্রো করবে। একটা উদাহরণ দেখা যাক:
>>> A = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
>>> A
{'apple', 'orange', 'banana', 'pear'}
>>> A.remove('apple')
>>> A
{'orange', 'banana', 'pear'}
>>> A.remove('berry')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'berry'
>>> A
{'orange', 'banana', 'pear'}
যদি এই এররটা পেতে না চাই তখন? সেক্ষেত্রে আমাদেরকে discard()
ফাংশনটা ব্যবহার করতে হবে। এই ফাংশনের ভিতর যা দেব সেটা যদি সেটে থেকে থাকে তবে রিমুভ হয়ে যাবে। আর না থাকলে কিছুই ঘটবে না। একটা উদাহরণ দেখা যাক:
>>> A = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
>>> A
{'apple', 'orange', 'banana', 'pear'}
>>> A.discard('apple')
>>> A
{'orange', 'banana', 'pear'}
>>> A.discard('berry')
>>> A
{'orange', 'banana', 'pear'}
ধরা যাক, A সেটের প্রথম উপাদানটা শুধু আমাদের দরকার। আমরা এটাকে বাদ দিয়ে দিতে চাই। এইক্ষেত্রে আমরা pop()
ফাংশনটা ব্যবহার করব। এই ফাংশন একটা সেটের প্রথম উপাদানটা রিমুভ করে দেয় আর তারপর সেটাকে রিটার্ন করে। যেমন:
>>> A = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
>>> A
{'pear', 'banana', 'apple', 'orange'}
>>> A.pop()
'pear'
>>> A.pop()
'banana'
>>> A.pop()
'apple'
যদি আমরা আমাদের A সেটের সব এলিমেন্টকে একটা স্টেটমেন্ট দিয়াই খাইয়া দিতে চাই? তখন কি করব? তখন আমরা clear()
ফাংশনটা ব্যবহার করব। যেমন:
>>> A
{'r', 'apple', 'pineapple', 'b', 'orange', 'banana', 'y', 'g', 'a', 'p', 'berry', 'grape', 'e', 'pear'}
>>> A.clear()
>>> A
set()
ইউনিয়ন #
দুইটা সেটের ইউনিয়ন করা মানে এমন একটা নতুন সেট গঠন করা যেখানে দুই সেটের উপাদানগুলোই থাকবে। A = {1, 2, 3, 4, 5} ও B = {6, 7, 8} দুইটা সেট হলে, তাদের ইউনিয়ন সেট C = {1, 2, 3, 4, 5, 6, 7, 8}। এই একই কাজ পাইথন দিয়ে করতে হলে আমাদের ব্যবহার করতে হবে union()
ফাংশন। একটা উদাহরণ দেখা যাক:
>>> A = {1, 2, 3, 4, 5}
>>> B = {6, 7, 8}
>>> A.union(B)
{1, 2, 3, 4, 5, 6, 7, 8}
A আর B দুইটা সেট। তৃতীয় স্টেটমেন্টের মাধ্যমে আমরা এদের ইউনিয়ন সেট তৈরি করেছি।
ইন্টারসেকশন #
দুইটা সেটের ইন্টারসেকশন করা মানে এমন একটা নতুন সেট গঠন করা যেখানে দুই সেটের কমন উপাদানগুলোই শুধু থাকবে। A = {1, 2, 3, 4, 5} ও B = {2, 3, 4, 5, 6, 7} দুইটা সেট হলে, তাদের ইন্টারসেকশন সেট C = {2, 3, 4, 5}। এই একই কাজ পাইথন দিয়ে করতে হলে আমাদের ব্যবহার করতে হবে intersection()
ফাংশন। একটা উদাহরণ দেখা যাক:
>>> A = {1, 2, 3, 4, 5}
>>> B = {2, 3, 4, 5, 6, 7}
>>> A.intersection(B)
{2, 3, 4, 5}
A আর B দুইটা সেট। তৃতীয় স্টেটমেন্টের মাধ্যমে আমরা এদের ইন্টারসেকশন সেট তৈরি করেছি।
ডিফারেন্স #
ধরা যাক, A = {1, 2, 3, 4, 5, 6} ও B= {5, 6, 7, 8} দুইটা সেট আর আমরা A - B বের করব। এইক্ষেত্রে নতুন যে সেটটা তৈরি হবে সেখানে B সেটের কোন উপাদান থাকতে পারবে না। আবার B - A এর ক্ষেত্রে A সেটের কোন উপাদান থাকতে পারবে না। পাইথন দিয়ে A - B বের করতে গেলে difference()
ফাংশন ব্যবহার করতে হবে আমাদের। যেমন:
>>> A = {1, 2, 3, 4, 5, 6}
>>> B= {5, 6, 7, 8}
>>> A.difference(B)
{1, 2, 3, 4}
সেট আপাতত এই পর্যন্তই থাক। সামনে অবশ্য আমরা আরো কিছু অপারেশন শিখব।