अध्याय 16

सेट — डुप्लिकेट्स के बिना एक संग्रह

डुप्लिकेट्स हटाना, दो संग्रहों की तुलना करने वाले चार प्रतीक, {} खाली सेट क्यों नहीं है, और सेट में क्रम न होने का वास्तविक अर्थ क्या है।

28 मिनटPython 3.12
  1. 1समस्या
  2. 2समझें
  3. 3उदाहरण
  4. 4अनुमान
  5. 5स्वयं करें
  6. 6चुनौती

वह समस्या जिसे हम हल कर रहे हैं

एक दिन की बिक्री की सूची आती है, प्रति बिक्री एक प्रविष्टि:

python
sold = ["pen", "bag", "pen", "ink", "pen"]

प्रश्न: कितने अलग-अलग उत्पाद बिके? len(sold) पाँच कहता है, लेकिन वह बिक्री की संख्या है। केवल तीन अलग उत्पाद थे।

पिछले अध्याय इसे प्रबंधित कर सकते हैं — एक खाली सूची शुरू करें, और प्रत्येक आइटम के लिए जोड़ने से पहले if item not in unique: की जाँच करें। छह पंक्तियाँ, और यह काम करता है।

लेकिन यदि प्रश्न यह है कि "सोमवार और मंगलवार दोनों दिन कौन से उत्पाद बिके?" तो आपको दो नेस्टेड लूप की आवश्यकता होगी। "केवल सोमवार?" — एक और। ये प्रश्न इतने सामान्य हैं कि गणित में इनकी अपनी एक शाखा है, और पायथन में उस गणित को सीधे लिखा जा सकता है।

एक सेट (Set) इसके लिए कंटेनर है: इसमें कोई डुप्लिकेट नहीं होते, और यह "दोनों में", "एक में लेकिन दूसरे में नहीं" जैसे प्रश्नों का उत्तर एक ही प्रतीक से देता है।

इस मिशन के अंत तक आप सीखेंगे

  • एक सेट बनाना, और एक सूची से डुप्लिकेट हटाना
  • |, &, - और ^ के साथ दो सेटों की तुलना करना
  • यह समझाना कि {} एक खाली सेट क्यों नहीं है
  • यह जानना कि एक सेट में कोई क्रम नहीं होता, और यह कब मायने रखता है
  • क्रम बनाए रखते हुए डुप्लिकेट हटाने वाला पैटर्न लिखना

पूर्वापेक्षाएँ: डिक्शनरी — की और मान के जोड़े.


सेट — डुप्लिकेट्स के बिना एक संग्रह

python
sold = ["pen", "bag", "pen", "ink", "pen"]

unique = set(sold)
print(sorted(unique))
print(len(unique))
text
['bag', 'ink', 'pen']
3

set(...) एक सूची लेता है और डुप्लिकेट हटा देता है। तीन pen एक बन जाते हैं।

प्रिंट करने के आसपास sorted() पर ध्यान दें, जो जानबूझकर किया गया है — कारण जल्द ही स्पष्ट होगा।

आप मँझले कोष्ठक {} के साथ सीधे भी एक सेट लिख सकते हैं:

python
letters = {"a", "b", "a"}
print(sorted(letters))
print(len(letters))
text
['a', 'b']
2

दूसरा "a" चुपचाप गायब हो गया। कोई त्रुटि नहीं — एक सेट में एक ही चीज़ के दो बार आने की कोई अवधारणा नहीं है।

{} खाली सेट नहीं है

python
not_a_set = {}
real_set = set()

print(type(not_a_set))
print(type(real_set))
text
<class 'dict'>
<class 'set'>

मँझले कोष्ठक पहले डिक्शनरी के लिए आए थे, इसलिए खाली {} एक डिक्शनरी ही रहा। खाली सेट के लिए आपको set() लिखना होगा।

इसमें कोई क्रम नहीं होता

यह एक सेट की सबसे महत्वपूर्ण सीमा है, और इसका सबसे गलत समझा जाने वाला गुण है।

सेट की चीज़ें किसी क्रम में नहीं होतीं। कोई इंडेक्स नहीं है और कोई स्लाइस नहीं है:

python
tags = {"new", "sale"}
print(tags[0])
text
TypeError: 'set' object is not subscriptable

और जब आप इसे प्रिंट करते हैं तो जो क्रम दिखता है वह भरोसेमंद नहीं होता — एक ही प्रोग्राम को दो बार चलाएं और यह भिन्न हो सकता है। इसीलिए इस अध्याय का प्रत्येक उदाहरण प्रिंट करने से पहले सॉर्ट करता है।

सूची से डुप्लिकेट हटाने का सबसे छोटा तरीका list(set(sold)) है, लेकिन यह मूल क्रम को फेंक देता है। जब क्रम मायने रखता है, तो एक सेट और एक सूची का एक साथ उपयोग करें:

python
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)
text
['pen', 'bag', 'ink']

सूची क्रम रखती है और सेट याद रखता है कि क्या देखा जा चुका है।

जोड़ना और हटाना

python
tags = {"new"}

tags.add("sale")
tags.add("new")
print(sorted(tags))

tags.discard("gone")
tags.remove("sale")
print(sorted(tags))
text
['new', 'sale']
['new']

add एक चीज़ अंदर रखता है — और यदि यह पहले से ही मौजूद है, तो कुछ नहीं होता और कोई शिकायत नहीं होती।

हटाना दो रूपों में आता है:

python
tags = {"new"}
tags.remove("gone")
text
KeyError: 'gone'

remove वस्तु न मिलने पर रुक जाता है; discard चुप रहता है। यदि वस्तु को वहाँ होना ही चाहिए, तो remove लिखें ताकि उसकी अनुपस्थिति पकड़ी जा सके।

दो सेटों की तुलना करना

यहाँ सेट वास्तव में अपना मूल्य सिद्ध करते हैं:

python
monday = {"rafi", "ahmed", "bilal"}
tuesday = {"ahmed", "dia"}

print(sorted(monday | tuesday))
print(sorted(monday & tuesday))
print(sorted(monday - tuesday))
print(sorted(monday ^ tuesday))
text
['ahmed', 'bilal', 'dia', 'rafi']
['ahmed']
['bilal', 'rafi']
['bilal', 'dia', 'rafi']

चार प्रतीक, चार प्रश्न:

  • | — दोनों में से किसी में भी (union)।
  • & — दोनों में (intersection)।
  • - — पहले में लेकिन दूसरे में नहीं (difference)।
  • ^ — ठीक एक में (symmetric difference)।

ध्यान दें कि - क्रम की परवाह करता है: monday - tuesday और tuesday - monday अलग-अलग उत्तर देते हैं।

इसमें क्या जा सकता है

डिक्शनरी कीज़ जैसा ही नियम: आप जो कुछ भी डालते हैं उसका अपरिवर्तनीय (immutable) होना आवश्यक है।

python
s = set()
s.add([1, 2])
text
TypeError: unhashable type: 'list'

टेक्स्ट, संख्याएं और टपल ठीक हैं; लिस्ट और डिक्शनरी नहीं।


एक संपूर्ण उदाहरण

sales.py:

python
# कौन से उत्पाद दोनों दिन बिके, और कौन से केवल एक दिन
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)
text
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

जब यह टूटता है

AttributeError: 'dict' object has no attribute 'add' सेट समझकर s = {} लिखा गया, लेकिन वह एक खाली डिक्शनरी है। s = set() लिखें।

TypeError: 'set' object is not subscriptable s[0] लिखा गया। एक सेट में कोई क्रम नहीं होता, इसलिए इसमें कोई इंडेक्स नहीं होता।

KeyError: 'gone' remove से ऐसी चीज़ हटाने को कहा गया जो सेट में नहीं है। यदि दोनों स्थितियाँ सामान्य हैं, तो discard का उपयोग करें।

TypeError: unhashable type: 'list' सेट में लिस्ट डालने का प्रयास। इसे tuple(...) में बदलें।