अध्याय 13

लिस्ट सॉर्ट करना और उसके मेथड्स

sorted() और .sort() का अंतर, max/min/sum/count/index, key= के साथ सॉर्टिंग के नियम बदलना, और join() से लिस्ट को पठनीय टेक्स्ट में बदलना।

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

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

एक सूची में सात लोगों के अंक (marks) हैं। तीन प्रश्नों के उत्तर देने की आवश्यकता है: सबसे अधिक अंक क्या हैं, औसत क्या है, और शीर्ष तीन (top three) कौन हैं?

अध्याय 12 के उपकरणों के साथ पहले दो सवालों का जवाब एक लूप के साथ दिया जा सकता है — कठिन है, लेकिन संभव है। तीसरा अलग है। "शीर्ष तीन" का अर्थ है पहले उन्हें एक क्रम में व्यवस्थित करना (sort करना), और हमारे पास अभी कुछ भी सॉर्ट करने का कोई तरीका नहीं है।

ये काम इतनी बार सामने आते हैं कि पायथन इन्हें पहले से तैयार करके प्रदान करता है। आज का अध्याय उपकरणों की वही सूची है — और एक ऐसा जाल जिसमें लगभग हर कोई कम से कम एक बार गिरता है: एक ही ऑपरेशन के दो रूप होते हैं, एक जो सूची को बदलता है और एक जो एक नई सूची वापस लौटाता है, और गलत का चुनाव करने पर कोई त्रुटि (error) भी नहीं आती।

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

  • sorted() और .sort() के बीच अंतर बताना, और किस काम के लिए कौन सा रूप चाहिए
  • max, min, sum, count और index के साथ लिस्ट से उत्तर निकालना
  • key= के साथ सॉर्टिंग का नियम बदलना
  • join() के साथ एक लिस्ट को पठनीय टेक्स्ट में बदलना
  • यह समझना कि मिश्रित प्रकारों (mixed types) की सूची को सॉर्ट करने पर TypeError क्यों आता है

पूर्वापेक्षाएँ: लिस्ट — एक ही नाम के तहत कई मान.


sorted() और .sort() — इस अध्याय का मुख्य बिंदु

दोनों सॉर्ट करते हैं। अंतर यह है कि वापस क्या मिलता है।

python
marks = [72, 45, 90, 61]

ordered = sorted(marks)
print(ordered)
print(marks)

marks.sort()
print(marks)
text
[45, 61, 72, 90]
[72, 45, 90, 61]
[45, 61, 72, 90]

आउटपुट की उन तीन पंक्तियों को ध्यान से पढ़ें।

sorted(marks) ने एक नई सॉर्ट की गई सूची बनाई और उसे वापस लौटाया। मूल marks सूची अछूती रही — दूसरी पंक्ति इसका प्रमाण है।

marks.sort() ने कुछ नया नहीं बनाया। इसने मूल सूची को ही सॉर्ट कर दिया, और पुराना क्रम हमेशा के लिए चला गया।

यह अध्याय 12 का नियम वापस आ रहा है: जो मेथड सूची को बदलता है वह कुछ भी वापस नहीं लौटाता।

python
marks = [72, 45, 90, 61]
marks = marks.sort()
print(marks)
text
None

बिल्कुल append की तरह। .sort() के साथ आपको परिणाम को संग्रहीत नहीं करना चाहिए; sorted() के साथ आपको करना चाहिए, अन्यथा काम बेकार चला जाता है।

कौन सा, कब? यदि मूल क्रम की अब आवश्यकता नहीं है, तो .sort() सरल और तेज़ है। यदि मूल सूची का उपयोग कहीं और किया जाता है, या आप निश्चित नहीं हैं, तो sorted() का उपयोग करें। संदेह होने पर, sorted() चुनें।

उल्टा क्रम, और संख्यात्मक उत्तर

python
marks = [72, 45, 90, 61]

print(sorted(marks, reverse=True))
print(max(marks), min(marks), sum(marks))
print(round(sum(marks) / len(marks), 2))
text
[90, 72, 61, 45]
90 45 268
67.0

max, min और sum मेथड नहीं बल्कि फ़ंक्शंस हैं, इसलिए यह max(marks) लिखा जाता है न कि marks.max()। औसत के लिए कुछ विशेष नहीं है: गिनती पर कुल योग ही औसत है, और round(..., 2) इसे दिखाने के लिए व्यवस्थित करता है।

ध्यान दें कि अध्याय 10 का संचय करने वाला लूप एक ही पंक्ति में सिमट गया है।

गिनना और खोजना

python
marks = [72, 45, 90, 45, 61]

print(marks.count(45))
print(marks.index(45))
print(marks.index(90))
text
2
1
2

count(x) बताता है कि x कितनी बार आता है। index(x) बताता है कि पहला मान कहाँ है — दो 45 के साथ यह इंडेक्स 1 की रिपोर्ट करता है और दूसरे का कभी उल्लेख नहीं करता।

और जो चीज़ वहाँ नहीं है उसे खोजने पर प्रोग्राम रुक जाता है:

python
marks = [72, 45, 90]
print(marks.index(50))
text
ValueError: 50 is not in list

बिल्कुल remove की तरह। पहले if 50 in marks: के साथ जाँचने की आदत डालें।

टेक्स्ट को सॉर्ट करना, और key=

python
names = ["rafi", "Bilal", "ahmed"]

print(sorted(names))
print(sorted(names, key=str.lower))
text
['Bilal', 'ahmed', 'rafi']
['ahmed', 'Bilal', 'rafi']

लोग पहला परिणाम देखते हैं और सोचते हैं कि पायथन ने गलती कर दी। ऐसा नहीं है — यह वर्ण कोड (character code) द्वारा सॉर्ट करता है, और वहाँ प्रत्येक बड़ा अक्षर (capital letter) प्रत्येक छोटे अक्षर से पहले आता है। इसलिए Bilal सबसे आगे आ गया।

key=str.lower कहता है: सॉर्ट करते समय, प्रत्येक नाम के साथ ऐसा व्यवहार करें जैसे कि वह लोअरकेस हो। नाम स्वयं अपरिवर्तित रहते हैं — Bilal अभी भी अपनी पूंजी B के साथ प्रिंट होता है — केवल तुलना लोअरकेस रूप का उपयोग करती है।

key कोई भी नियम हो सकता है:

python
words = ["bag", "pen", "notebook", "ink"]
print(sorted(words, key=len))
text
['bag', 'pen', 'ink', 'notebook']

लंबाई के अनुसार क्रमबद्ध। ध्यान दें कि bag, pen और ink सभी तीन वर्ण लंबे हैं और उसी क्रम में रहे जिसमें वे पहले से थे — पायथन समान मानों के क्रम को नहीं बदलता। इस गुण को स्थिर सॉर्ट (stable sort) कहा जाता है।

मिश्रित प्रकारों को सॉर्ट नहीं किया जा सकता

python
values = [3, "1", 2]
print(sorted(values))
text
TypeError: '<' not supported between instances of 'str' and 'int'

सॉर्ट करने का अर्थ है जोड़ों में चीज़ों की तुलना करना, और अध्याय 8 ने दिखाया था कि संख्या और टेक्स्ट की तुलना < से नहीं की जा सकती।

लिस्ट से टेक्स्ट बनाना — join

एक सूची को सीधे प्रिंट करने से कोष्ठक और उद्धरण चिह्न (quotes) मिलते हैं, जो किसी व्यक्ति को दिखाने के लिए उपयुक्त नहीं है:

python
names = ["rafi", "ahmed", "bilal"]

print(", ".join(names))
print(" | ".join(names))
text
rafi, ahmed, bilal
rafi | ahmed | bilal

जुड़ने वाला टेक्स्ट पहले आता है, और सूची कोष्ठक में जाती है। इसे याद रखने का तरीका — "इनको इसके साथ जोड़ें"।

एक सख्त शर्त है: प्रत्येक मान टेक्स्ट होना चाहिए।

python
marks = [72, 45, 90]
print(", ".join(marks))
text
TypeError: sequence item 0: expected str instance, int found

संख्याओं की सूची को जोड़ने के लिए, पहले प्रत्येक को टेक्स्ट में बदलें:

python
marks = [72, 45, 90]
print(", ".join(str(m) for m in marks))
text
72, 45, 90

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

report.py:

python
# एक अंक रिपोर्ट: उन्हें क्रमबद्ध करें, सारांशित करें और शीर्ष तीन दिखाएं
marks = [72, 45, 90, 61, 88, 45, 33]

ordered = sorted(marks, reverse=True)

print("Marks    :", marks)
print("Ordered  :", ordered)
print("Count    :", len(marks))
print("Highest  :", max(marks))
print("Lowest   :", min(marks))
print("Total    :", sum(marks))
print("Average  :", round(sum(marks) / len(marks), 2))
print("How many 45s:", marks.count(45))

top_three = ordered[:3]
print("Top three:", top_three)
print("As text  :", ", ".join(str(m) for m in top_three))

passed = []
for mark in marks:
    if mark >= 40:
        passed.append(mark)

print("Passed   :", len(passed), "of", len(marks))
text
Marks    : [72, 45, 90, 61, 88, 45, 33]
Ordered  : [90, 88, 72, 61, 45, 45, 33]
Count    : 7
Highest  : 90
Lowest   : 33
Total    : 434
Average  : 62.0
How many 45s: 2
Top three: [90, 88, 72]
As text  : 90, 88, 72
Passed   : 6 of 7

दो डिज़ाइन निर्णय ध्यान देने योग्य हैं:

.sort() के स्थान पर sorted() को चुना गया क्योंकि पहली पंक्ति में मूल marks को फिर से प्रिंट किया जाता है। .sort() के साथ, "Marks" और "Ordered" पंक्तियाँ एक ही चीज़ दिखातीं और कोई त्रुटि भी नहीं आती।

शीर्ष तीन एक स्लाइस से आए — ordered[:3]। किसी अलग "टॉप थ्री" फ़ंक्शन की आवश्यकता नहीं थी: घटते क्रम वाली सूची के पहले तीन ही शीर्ष तीन होते हैं।


जब यह टूटता है

सॉर्ट करने के बाद मेरी लिस्ट None हो गई पंक्ति में marks = marks.sort() लिखा गया था। .sort() स्वयं सूची को सॉर्ट करता है और None लौटाता है — केवल marks.sort() लिखें। नई सूची के लिए ordered = sorted(marks) का उपयोग करें।

सॉर्ट करने से मूल सूची भी बदल गई आपने .sort() का उपयोग किया था, जो यथास्थान (in place) सॉर्ट करता है। मूल को अछूता छोड़ने के लिए sorted() का उपयोग करें।

TypeError: '<' not supported between instances of 'str' and 'int' सूची में संख्याएँ और टेक्स्ट मिश्रित हैं। फ़ाइल से पढ़े जाने पर वे संभवतः सभी स्ट्रिंग होते हैं, और उन्हें int() की आवश्यकता होती है।

ValueError: 50 is not in list index() या remove() को ऐसा मान दिया गया था जो सूची में नहीं है। पहले in से जाँचें।

TypeError: sequence item 0: expected str instance, int found join() को संख्याओं की सूची दी गई थी। प्रत्येक को str() में लपेटें।