सेट — बिना डुप्लिकेट वाला कलेक्शन
डुप्लिकेट्स हटाना, दो कलेक्शन की तुलना करने वाले चार चिह्न, {} खाली सेट क्यों नहीं है, और सेट में क्रम न होने का असली मतलब क्या है।
आप कैसे सीखना चाहते हैं?
वह समस्या जिसे हम हल कर रहे हैं
एक दिन की बिक्री की लिस्ट आई है — हर बिक्री की एक एंट्री:
sold = ["pen", "bag", "pen", "ink", "pen"]सवाल: कितनी तरह के प्रोडक्ट बिके? len(sold) पाँच बताएगा, लेकिन वह बिक्री की गिनती है। अलग-अलग प्रोडक्ट तीन हैं।
पिछले अध्यायों के टूल से यह हो सकता है — एक खाली लिस्ट लें, और हर प्रोडक्ट पर if item not in unique: देखकर उसे जोड़ें। छह लाइनें, और काम हो जाता है।
लेकिन अगर सवाल हो “सोमवार और मंगलवार, दोनों दिन कौन-से प्रोडक्ट बिके?” — तब दो नेस्टेड लूप चाहिए। “सिर्फ़ सोमवार?” — एक और। ये सवाल इतने आम हैं कि इनका अपना गणित है, और Python में वह गणित सीधे लिखा जा सकता है।
सेट वही कंटेनर है: यह डुप्लिकेट नहीं रखता, और “दोनों में है”, “एक में है, दूसरे में नहीं” जैसे सवालों का जवाब एक अक्षर से देता है।
इस अध्याय के अंत तक आप कर पाएंगे
- सेट बनाना, और एक लिस्ट से डुप्लिकेट हटाना
|,&,-,^से दो सेट की तुलना करना- बताना कि
{}खाली सेट क्यों नहीं है - जानना कि सेट में क्रम नहीं होता, और यह कब समस्या बनता है
- क्रम बनाए रखते हुए डुप्लिकेट हटाने वाला पैटर्न लिखना
पहले से क्या आना चाहिए: डिक्शनरी — key और वैल्यू की जोड़ी।
सेट — बिना डुप्लिकेट वाला कलेक्शन
sold = ["pen", "bag", "pen", "ink", "pen"]
unique = set(sold)
print(sorted(unique))
print(len(unique))['bag', 'ink', 'pen']
3set(...) एक लिस्ट लेता है और डुप्लिकेट हटा देता है। तीन बार वाला pen एक ही बार रहता है।
ध्यान दें कि प्रिंट करते समय sorted() लिखा गया है, और यह जानबूझकर है — इसकी वजह थोड़ी देर में आ रही है।
सेट सीधे भी बनाया जा सकता है, कर्ली ब्रैकेट से:
letters = {"a", "b", "a"}
print(sorted(letters))
print(len(letters))['a', 'b']
2दूसरा "a" चुपचाप गायब हो गया। कोई एरर नहीं — सेट में एक ही चीज़ के दो बार होने का कोई मतलब ही नहीं है।
{} खाली सेट नहीं है
not_a_set = {}
real_set = set()
print(type(not_a_set))
print(type(real_set))<class 'dict'>
<class 'set'>कर्ली ब्रैकेट पहले से ही डिक्शनरी के लिए इस्तेमाल होते थे, इसलिए खाली {} डिक्शनरी ही रह गया। खाली सेट चाहिए तो set() लिखना पड़ता है।
यह गलती शुरू में चुप रहती है: {} से शुरू करके .add() लिखें तो AttributeError आता है, और तब लगता है कि गड़बड़ add में है।
क्रम नहीं होता
यह सेट की सबसे ज़रूरी सीमा है, और सबसे ज़्यादा गलत समझी जाने वाली खूबी भी।
सेट की चीज़ों का कोई क्रम नहीं होता। इंडेक्स नहीं, स्लाइस नहीं:
tags = {"new", "sale"}
print(tags[0])TypeError: 'set' object is not subscriptableऔर प्रिंट करने पर जिस क्रम में चीज़ें दिखती हैं, वह भरोसेमंद नहीं है — एक ही प्रोग्राम दो बार चलाएँ तो क्रम अलग हो सकता है। इसीलिए इस अध्याय के हर उदाहरण में प्रिंट से पहले sorted() लिखा है: सेट को सीधे प्रिंट करने पर आप जो देख रहे हैं, अगली बार भी वही दिखेगा इसकी कोई गारंटी नहीं।
लिस्ट से डुप्लिकेट हटाने का सबसे छोटा तरीका list(set(sold)) है, लेकिन यह मूल क्रम बिगाड़ देता है। क्रम चाहिए तो सेट और लिस्ट को साथ में इस्तेमाल करें:
sold = ["pen", "bag", "pen", "ink", "bag"]
seen = set()
unique = []
for item in sold:
if item not in seen:
seen.add(item)
unique.append(item)
print(unique)['pen', 'bag', 'ink']लिस्ट क्रम रख रही है, और सेट याद रख रहा है कि “पहले देखा है या नहीं”। यह जोड़ी एक बहुत आम पैटर्न है।
जोड़ना और हटाना
tags = {"new"}
tags.add("sale")
tags.add("new")
print(sorted(tags))
tags.discard("gone")
tags.remove("sale")
print(sorted(tags))['new', 'sale']
['new']add एक चीज़ जोड़ता है — और अगर वह पहले से है, तो कुछ नहीं होता, कोई शिकायत भी नहीं। लिस्ट का append दूसरी कॉपी बना देता; सेट नहीं बनाता।
हटाने के दो तरीके हैं, और इनका फ़र्क काम का है:
tags = {"new"}
tags.remove("gone")KeyError: 'gone'remove चीज़ न मिलने पर रुक जाता है; discard चुपचाप छोड़ देता है। अगर चीज़ का होना ज़रूरी है तो remove लिखें, ताकि न होने पर वह पकड़ में आ जाए।
दो सेट की तुलना
यहीं सेट सच में काम आता है:
monday = {"rafi", "ahmed", "bilal"}
tuesday = {"ahmed", "dia"}
print(sorted(monday | tuesday))
print(sorted(monday & tuesday))
print(sorted(monday - tuesday))
print(sorted(monday ^ tuesday))['ahmed', 'bilal', 'dia', 'rafi']
['ahmed']
['bilal', 'rafi']
['bilal', 'dia', 'rafi']चार चिह्न, चार सवाल:
|— किसी में भी है (union)। दो दिनों में कुल कौन-कौन आया।&— दोनों में है (intersection)। दोनों दिन कौन आया।-— पहले में है, दूसरे में नहीं (difference)। सिर्फ़ सोमवार कौन आया।^— ठीक एक में है (symmetric difference)। जो एक दिन आए, दोनों दिन नहीं।
ध्यान दें कि - में क्रम मायने रखता है: monday - tuesday और tuesday - monday अलग जवाब देते हैं। बाकी तीन दोनों तरफ़ से एक ही जवाब देते हैं।
लूप से ये चारों लिखने में हर एक के लिए कई लाइनें लगतीं, और कम से कम एक में गलती होने की अच्छी-खासी संभावना रहती।
सेट में क्या-क्या रखा जा सकता है
डिक्शनरी की key जैसा ही नियम: जो रखेंगे वह immutable (न बदलने वाला) होना चाहिए।
s = set()
s.add([1, 2])TypeError: unhashable type: 'list'हूबहू वही मैसेज, उसी वजह से — सेट भी अंदर हैश इस्तेमाल करता है। स्ट्रिंग, नंबर, टपल चलते हैं; लिस्ट और डिक्शनरी नहीं चलते।
एक पूरा उदाहरण
sales.py:
# Which products sold on both days, and which only on one
monday = ["pen", "bag", "pen", "ink"]
tuesday = ["ink", "bottle", "pen", "ink"]
mon = set(monday)
tue = set(tuesday)
print("Monday sold :", sorted(mon), f"({len(monday)} sales, {len(mon)} products)")
print("Tuesday sold :", sorted(tue), f"({len(tuesday)} sales, {len(tue)} products)")
print()
print("Either day :", sorted(mon | tue))
print("Both days :", sorted(mon & tue))
print("Monday only :", sorted(mon - tue))
print("Exactly one day:", sorted(mon ^ tue))
print()
print("Was ink sold on Monday?", "ink" in mon)Monday sold : ['bag', 'ink', 'pen'] (4 sales, 3 products)
Tuesday sold : ['bottle', 'ink', 'pen'] (4 sales, 3 products)
Either day : ['bag', 'bottle', 'ink', 'pen']
Both days : ['ink', 'pen']
Monday only : ['bag']
Exactly one day: ['bag', 'bottle']
Was ink sold on Monday? Trueतीन बातें ध्यान देने लायक हैं।
मूल लिस्ट रखी गई हैं। len(monday) बता रहा है चार बिक्री, len(mon) बता रहा है तीन तरह के प्रोडक्ट। सेट में बदलने के बाद बिक्री की गिनती पता नहीं चलती — इसलिए सेट मूल डेटा का विकल्प नहीं है, बल्कि उस पर एक तरह का सवाल पूछने का टूल है।
हर प्रिंट से पहले sorted()। इसके बिना क्रम बेतरतीब दिखता, और हर बार चलाने पर बदल भी सकता था।
"ink" in mon लिखा है, "ink" in monday नहीं। दोनों True देते, लेकिन सेट में ढूँढना लिस्ट में ढूँढने से तेज़ है — लिस्ट में Python एक-एक करके मिलाता है, सेट में वह हैश से सीधे उस जगह पहुँच जाता है। चार चीज़ों में इसका कोई मतलब नहीं; चालीस हज़ार में है।
जब कुछ टूट जाए
AttributeError: 'dict' object has no attribute 'add' s = {} लिखकर उसे सेट समझा गया, लेकिन वह एक खाली डिक्शनरी है। s = set() लिखें।
TypeError: 'set' object is not subscriptable s[0] लिखा गया है। सेट में क्रम नहीं है, इसलिए इंडेक्स भी नहीं। किसी खास चीज़ की ज़रूरत है तो शायद लिस्ट या डिक्शनरी चाहिए थी; नहीं तो sorted(s) से एक लिस्ट बना लें।
KeyError: 'gone' remove से ऐसी चीज़ हटाने को कहा गया जो सेट में नहीं है। अगर होना-न-होना दोनों सामान्य हैं तो discard इस्तेमाल करें।
TypeError: unhashable type: 'list' सेट में लिस्ट रखने की कोशिश। उसे tuple(...) से बदल लें।
list(set(...)) के बाद क्रम बिगड़ गया यह सामान्य है, सेट में क्रम नहीं होता। क्रम चाहिए तो ऊपर वाला seen पैटर्न इस्तेमाल करें, या sorted()।
दो सेट को == से मिला रहा हूँ, क्रम अलग होने पर भी True आ रहा है सही आ रहा है। दो सेट बराबर होते हैं अगर उनके अंदर की चीज़ें एक जैसी हों — क्रम की कोई भूमिका नहीं। लिस्ट में [1, 2] == [2, 1] False है, सेट में {1, 2} == {2, 1} True है।
चरण 4 / 6 — अनुमान
अपनी समझ की जाँच करें
दो खाली कंटेनर बनाए गए हैं। type() क्या बताएगा?
not_a_set = {}
real_set = set()
print(type(not_a_set))
print(type(real_set))- A<class 'dict'> <class 'set'>
- B<class 'set'> <class 'set'>
- C<class 'set'> <class 'dict'>
- D<class 'dict'> <class 'dict'>
& और - किन दो सवालों का जवाब दे रहे हैं?
monday = {"rafi", "ahmed", "bilal"}
tuesday = {"ahmed", "dia"}
print(sorted(monday & tuesday))
print(sorted(monday - tuesday))- A['bilal', 'rafi'] ['ahmed']
- B['ahmed', 'bilal', 'dia', 'rafi'] ['ahmed']
- C['ahmed'] ['bilal', 'rafi']
- D['ahmed'] ['dia']
सेट की पहली चीज़ माँगी गई है। क्या होगा?
tags = {"new", "sale"}
print(tags[0])- Anew
- Bsale
- C`TypeError` — सेट में कोई क्रम नहीं, इसलिए इंडेक्स भी नहीं
- D`KeyError`
उत्तर देने के लिए अकाउंट आवश्यक है
अपने उत्तर जाँचने के लिए साइन इन करें
प्रश्न ऊपर दिए गए हैं, और मन में उत्तर सोचना ही मुख्य कार्य है। सही उत्तर, व्याख्या और तीन-स्तरीय संकेत देखने के लिए साइन इन करें।
आपकी बारी
visitors.py नाम की एक फ़ाइल लिखें, जिसमें तीन दिनों के विज़िटर की तीन लिस्ट हों — हर लिस्ट में कुछ नाम, और कुछ नाम एक से ज़्यादा दिन।
फिर प्रिंट करें:
- हर दिन कितने लोग आए, और कितने अलग-अलग लोग आए
- तीन दिनों में कुल कितने अलग-अलग लोग
- वे लोग जो तीनों दिन आए
- वे लोग जो सिर्फ़ पहले दिन आए
- वे लोग जो पहले दो दिनों में से ठीक एक दिन आए
फिर दो प्रयोग:
- डुप्लिकेट हटाने के दो तरीके लिखें —
list(set(...))और ऊपर वालाseenपैटर्न — और दोनों के नतीजे साथ-साथ प्रिंट करें। फ़र्क क्या है? - खाली सेट बनाने के लिए
{}लिखकर उस पर.add()चलाने की कोशिश करें। कौन-सा एरर आता है, और मैसेज किस तरह के ऑब्जेक्ट का नाम लेता है?
दूसरा प्रयोग छोटा है, लेकिन एक बार अपनी आँखों से देख लेने के बाद यह गलती फिर कभी आपके दस मिनट बर्बाद नहीं करेगी।
चरण 6 / 6
चुनौती — अध्याय की क्विज़
सरल से कठिन — दस प्रश्न, अंतिम वाले जानबूझकर चुनौतीपूर्ण बनाए गए हैं।
क्विज़ देने के लिए साइन इन करें