लिस्ट सॉर्ट करना और उसके मेथड्स
sorted() और .sort() का अंतर, max/min/sum/count/index, key= के साथ सॉर्ट करने का नियम बदलना, और join() से लिस्ट को पढ़ने लायक़ स्ट्रिंग में बदलना।
आप कैसे सीखना चाहते हैं?
वह समस्या जिसे हम हल कर रहे हैं
सात लोगों के नंबर एक लिस्ट में हैं। तीन सवालों के जवाब देने हैं: सबसे ज़्यादा कितना, औसत कितना, और टॉप तीन कौन हैं?
पिछले अध्याय के टूल से पहले दो सवालों के जवाब लूप लिखकर निकाले जा सकते हैं — मेहनत वाला काम, लेकिन हो जाता है। तीसरा अलग है। "टॉप तीन" का मतलब है पहले सॉर्ट करना, और सॉर्ट करने का कोई तरीक़ा अभी हमारे पास नहीं है।
ये काम इतनी बार पड़ते हैं कि Python ने इन्हें खुद ही दे रखा है। आज का अध्याय वही टूल हैं — और साथ में एक जाल जिसमें लगभग हर कोई कम से कम एक बार फँसता है: एक ही काम के दो रूप हैं, एक लिस्ट को ही बदल देता है और दूसरा नई लिस्ट लौटाता है, और ग़लत चुनने पर कोई एरर नहीं आता।
इस अध्याय के बाद आप यह कर पाएँगे
sorted()और.sort()का फ़र्क़ बताना, और कब कौन चाहिए यह जाननाmax,min,sum,count,indexसे लिस्ट से जवाब निकालनाkey=से सॉर्ट करने का नियम बदलनाjoin()से एक लिस्ट को पढ़ने लायक़ स्ट्रिंग में बदलना- अलग-अलग टाइप वाली लिस्ट सॉर्ट करने पर
TypeErrorक्यों आता है, यह बताना
पहले यह आना चाहिए: लिस्ट — एक ही नाम में कई वैल्यू।
sorted() और .sort() — इस अध्याय की मुख्य बात
दोनों सॉर्ट करते हैं। फ़र्क़ यह है कि लौटकर क्या लाते हैं।
marks = [72, 45, 90, 61]
ordered = sorted(marks)
print(ordered)
print(marks)
marks.sort()
print(marks)[45, 61, 72, 90]
[72, 45, 90, 61]
[45, 61, 72, 90]तीनों लाइनें ध्यान से पढ़िए।
sorted(marks) ने एक नई सॉर्ट की हुई लिस्ट बनाकर लौटाई। असली marks बिल्कुल पहले जैसी रही — दूसरी लाइन इसी का सबूत है।
marks.sort() ने कोई नई लिस्ट नहीं बनाई। उसने असली लिस्ट को ही सॉर्ट कर दिया, और पुराना क्रम हमेशा के लिए खो गया।
पिछले अध्याय का नियम यहाँ फिर लौट आया है: जो मेथड लिस्ट को बदलता है, वह कुछ नहीं लौटाता।
marks = [72, 45, 90, 61]
marks = marks.sort()
print(marks)Noneबिल्कुल append की तरह। .sort() लिखें तो नतीजा पकड़कर नहीं रखना; sorted() लिखें और नतीजा न पकड़ें तो काम ही बेकार।
कब कौन? असली क्रम अब नहीं चाहिए तो .sort() आसान और सस्ता है। असली लिस्ट कहीं और इस्तेमाल हो रही है, या आप पक्का नहीं जानते — तब sorted(), क्योंकि वह किसी की कोई चीज़ नहीं छीनता। शक हो तो sorted()।
उल्टा क्रम और नंबरों वाले जवाब
marks = [72, 45, 90, 61]
print(sorted(marks, reverse=True))
print(max(marks), min(marks), sum(marks))
print(round(sum(marks) / len(marks), 2))[90, 72, 61, 45]
90 45 268
67.0max, min, sum — तीनों फ़ंक्शन हैं, मेथड नहीं, इसलिए marks.max() नहीं बल्कि max(marks)। औसत के लिए अलग कुछ नहीं है: जोड़ को गिनती से भाग देना ही औसत है, और round(..., 2) दिखाने के लिए दो दशमलव तक ले आता है।
ध्यान दीजिए, अध्याय 10 में लूप से जमा करने वाला काम यहाँ एक लाइन में हो गया। लूप सीखना बेकार नहीं गया — sum जो कर रहा है वह ठीक वही लूप है, और किसी दिन कुछ ऐसा जमा करना पड़ेगा जिसके लिए Python में बना-बनाया फ़ंक्शन नहीं है।
गिनना और ढूँढना
marks = [72, 45, 90, 45, 61]
print(marks.count(45))
print(marks.index(45))
print(marks.index(90))2
1
2count(x) बताता है कि x कितनी बार है। index(x) बताता है कि पहली बार कहाँ है — दो 45 होने पर भी वह पहले वाले का इंडेक्स 1 देता है, दूसरे की बात नहीं करता।
और जो चीज़ है ही नहीं उसे ढूँढें तो index रुक जाता है:
marks = [72, 45, 90]
print(marks.index(50))ValueError: 50 is not in listबिल्कुल remove की तरह। पहले if 50 in marks: से देख लेने की आदत डालिए।
स्ट्रिंग सॉर्ट करना, और key=
names = ["rafi", "Bilal", "ahmed"]
print(sorted(names))
print(sorted(names, key=str.lower))['Bilal', 'ahmed', 'rafi']
['ahmed', 'Bilal', 'rafi']पहला नतीजा देखकर बहुत लोग सोचते हैं कि Python ने ग़लती की। नहीं की — वह अक्षरों के कोड नंबर से सॉर्ट करता है, और वहाँ सारे बड़े अक्षर (capital) सारे छोटे अक्षरों से पहले आते हैं। इसीलिए Bilal सबसे आगे चला गया।
key=str.lower कह रहा है: सॉर्ट करते समय हर नाम को छोटे अक्षरों वाला मान लो। नाम बदलते नहीं — प्रिंट हुए नतीजे में Bilal का बड़ा B वैसा ही है — बस तुलना करते समय छोटे अक्षरों वाला रूप इस्तेमाल होता है।
key कोई भी नियम हो सकता है:
words = ["bag", "pen", "notebook", "ink"]
print(sorted(words, key=len))['bag', 'pen', 'ink', 'notebook']लंबाई से सॉर्ट। ध्यान दीजिए, bag, pen, ink तीनों की लंबाई तीन है, और वे जिस क्रम में थे उसी क्रम में रहे — बराबर होने पर Python क्रम नहीं बिगाड़ता। इस ख़ासियत का नाम stable sort है, और कई शर्तों पर सॉर्ट करते समय यही काम आती है।
अलग-अलग टाइप सॉर्ट नहीं होते
values = [3, "1", 2]
print(sorted(values))TypeError: '<' not supported between instances of 'str' and 'int'सॉर्ट करने के लिए जोड़ी-जोड़ी में तुलना करनी पड़ती है, और अध्याय 8 में देखा था कि एक नंबर और एक स्ट्रिंग की < से तुलना नहीं हो सकती। इसलिए मैसेज भी हूबहू वही है। CSV फ़ाइल से पढ़ी गई लिस्ट में यह अक्सर होता है — वहाँ सारे नंबर असल में स्ट्रिंग होते हैं।
लिस्ट से स्ट्रिंग — join
लिस्ट सीधे प्रिंट करें तो स्क्वेयर ब्रैकेट और कोटेशन के साथ आती है, जो लोगों को दिखाने के लिए नहीं है:
names = ["rafi", "ahmed", "bilal"]
print(", ".join(names))
print(" | ".join(names))rafi, ahmed, bilal
rafi | ahmed | bilalयह लाइन पहली बार उल्टी लगती है: जोड़ने वाला निशान पहले आता है, और लिस्ट ब्रैकेट के अंदर। याद रखने का तरीक़ा — "इस निशान से इन्हें जोड़ दो"।
शर्त एक ही है, और सख़्त है: सारी वैल्यू स्ट्रिंग होनी चाहिए।
marks = [72, 45, 90]
print(", ".join(marks))TypeError: sequence item 0: expected str instance, int foundनंबरों की लिस्ट जोड़नी हो तो पहले हर एक को स्ट्रिंग में बदलना पड़ता है:
marks = [72, 45, 90]
print(", ".join(str(m) for m in marks))72, 45, 90str(m) for m in marks वाला हिस्सा नया है, और इसे पूरी तरह आगे के एक अध्याय में सिखाया जाएगा। अभी बस ऐसे पढ़िए: "marks के हर m को str(m) बनाओ।" फिर join उन स्ट्रिंग को जोड़ देता है। नीचे के पूरे उदाहरण में भी यही लाइन है।
एक पूरा उदाहरण
report.py:
# A marks report: order them, summarise them, and show the top three
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))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दो डिज़ाइन फ़ैसले ध्यान देने लायक़ हैं।
sorted() चुना गया, .sort() नहीं — क्योंकि पहली ही लाइन में असली marks फिर से प्रिंट हो रही है। .sort() लिखते तो "Marks" और "Ordered" दोनों लाइनें एक जैसी दिखतीं, और कोई एरर नहीं आता। यही वह चुपचाप होने वाली ग़लती है जिसकी बात इस अध्याय की शुरुआत में हुई थी।
टॉप तीन स्लाइस से निकले — ordered[:3]। "टॉप तीन" का अलग कोई फ़ंक्शन नहीं लगा: उल्टे क्रम में सॉर्ट हुई लिस्ट के पहले तीन ही टॉप तीन हैं। सॉर्ट करने के बाद बहुत से सवालों का जवाब ऐसे ही एक स्लाइस बन जाता है।
कुछ टूटी हुई हालतें और उनका हल
.sort() के बाद लिस्ट None हो गई marks = marks.sort() लिखा गया है। .sort() लिस्ट को ही सॉर्ट करता है और None लौटाता है — सिर्फ़ marks.sort() लिखिए। नई लिस्ट चाहिए तो ordered = sorted(marks)।
सॉर्ट के बाद असली लिस्ट भी बदल गई .sort() इस्तेमाल हुआ है, जो असली लिस्ट को ही सॉर्ट करता है। असली को जैसा का तैसा रखना है तो sorted() इस्तेमाल कीजिए।
TypeError: '<' not supported between instances of 'str' and 'int' लिस्ट में नंबर और स्ट्रिंग मिले हुए हैं। print(marks) करके देखिए कि कौन-सी वैल्यू कोटेशन में हैं; फ़ाइल से पढ़ी गई हो तो आमतौर पर सब स्ट्रिंग होती हैं, और int() से बदलनी पड़ती हैं।
ValueError: 50 is not in list index() या remove() को ऐसी वैल्यू दी गई जो लिस्ट में नहीं है। पहले in से देख लीजिए।
TypeError: sequence item 0: expected str instance, int found join() को नंबरों की लिस्ट दी गई है। हर एक को str() कर लीजिए।
नाम सॉर्ट करने पर बड़े अक्षर वाले नाम सब पहले आ गए यही सामान्य व्यवहार है, एरर नहीं। लोगों की उम्मीद के हिसाब से सॉर्ट करने के लिए sorted(names, key=str.lower)।
चरण 4 / 6 — अनुमान
अपनी समझ की जाँच करें
sorted() इस्तेमाल हुआ है। दोनों लाइनें क्या प्रिंट करेंगी?
marks = [72, 45, 90]
ordered = sorted(marks)
print(ordered)
print(marks)- A[45, 72, 90] [72, 45, 90]
- B[45, 72, 90] None
- C[45, 72, 90] [45, 72, 90]
- D[72, 45, 90] [45, 72, 90]
.sort() का नतीजा फिर से marks में रखा गया है। क्या प्रिंट होगा?
marks = [72, 45, 90]
marks = marks.sort()
print(marks)- Aएक `AttributeError`
- B[72, 45, 90]
- C[45, 72, 90]
- DNone
नंबरों की एक लिस्ट को कॉमा से जोड़ने की कोशिश। क्या होगा?
marks = [72, 45, 90]
print(", ".join(marks))- A`TypeError` — `join` सिर्फ़ स्ट्रिंग जोड़ सकता है
- B724590
- C72, 45, 90
- D[72, 45, 90]
उत्तर देने के लिए अकाउंट आवश्यक है
अपने उत्तर जाँचने के लिए साइन इन करें
प्रश्न ऊपर दिए गए हैं, और मन में उत्तर सोचना ही मुख्य कार्य है। सही उत्तर, व्याख्या और तीन-स्तरीय संकेत देखने के लिए साइन इन करें।
आपकी बारी
inventory.py नाम की एक फ़ाइल लिखिए, जिसमें कम से कम सात प्रोडक्ट के नामों की एक लिस्ट और उनकी क़ीमतों की एक लिस्ट हो।
क़ीमतों की लिस्ट से प्रिंट कीजिए:
- सबसे ज़्यादा, सबसे कम, जोड़ और औसत (औसत दो दशमलव तक)
- सॉर्ट की हुई एक नई लिस्ट — और फिर साबित कीजिए कि असली लिस्ट नहीं बदली
- सबसे महँगे तीन, स्लाइस से
नामों की लिस्ट से प्रिंट कीजिए:
- वर्णमाला के क्रम में, छोटे-बड़े अक्षरों को नज़रअंदाज़ करके
- नाम की लंबाई के हिसाब से सॉर्ट
- सारे नाम एक लाइन में, कॉमा से अलग —
joinसे
आख़िर में एक प्रयोग कीजिए: क़ीमतों की लिस्ट पर .sort() चलाइए, फिर काम नंबर 1 वाली लाइनें दोबारा प्रिंट कीजिए। कौन-सा नंबर बदला, और कौन-सा नहीं? जो नहीं बदले वे क्यों नहीं बदले, यह खुद को समझाइए — यह जवाब याद रहा तो इस अध्याय का जाल आपको फिर कभी नहीं पकड़ पाएगा।
चरण 6 / 6
चुनौती — अध्याय की क्विज़
सरल से कठिन — दस प्रश्न, अंतिम वाले जानबूझकर चुनौतीपूर्ण बनाए गए हैं।
क्विज़ देने के लिए साइन इन करें