नेस्टेड डेटा — डिक्शनरी की लिस्ट
वास्तविक डेटा का स्वरूप: लिस्ट के अंदर डिक्शनरी, डिक्शनरी के अंदर लिस्ट। अंदर तक पहुँचना, ग्रुप बनाना, और copy() यहाँ पर्याप्त क्यों नहीं है।
- 1समस्या
- 2समझें
- 3उदाहरण
- 4अनुमान
- 5स्वयं करें
- 6चुनौती
वह समस्या जिसे हम हल कर रहे हैं
पिछले तीन अध्यायों ने चार कंटेनर सिखाए — लिस्ट, टपल, डिक्शनरी, सेट। प्रत्येक उदाहरण ने उनमें से किसी एक का उपयोग किया, एक स्तर गहरा।
वास्तविक डेटा उस तरह नहीं आता है। ऑर्डर की एक सूची इस तरह दिखती है:
customer item quantity price
rafi pen 3 15.0
ahmed bag 1 850.0यहाँ दो स्तर हैं। बाहर एक संग्रह — ऑर्डर की संख्या ज्ञात नहीं है, इसलिए एक लिस्ट। अंदर, प्रत्येक ऑर्डर एक रिकॉर्ड है जिसके हर हिस्से का एक नाम है — इसलिए एक डिक्शनरी।
एपीआई से जो वापस आता है, सीएसवी पढ़ने से जो आपको मिलता है, डेटाबेस जो लौटाता है: लगभग हमेशा यही रूप होता है, डिक्शनरी की एक लिस्ट। आज का अध्याय कोई नया कंटेनर पेश नहीं करता है। यह आपके पास मौजूद कंटेनरों को एक-दूसरे के अंदर रखने और आने वाली गलतियों को पहचानने के बारे में है।
इस मिशन के अंत तक आप सीखेंगे
- डिक्शनरी की एक लिस्ट के अंदर तक पहुँचना और उस पर लूप चलाना
- एक गहरे
KeyErrorयाIndexErrorको पढ़ना और यह बताना कि किस स्तर पर गलती हुई - डिक्शनरी की एक लिस्ट को समूहीकृत (group) और सारांशित करना
.get()के डिफ़ॉल्ट मान के साथ अपूर्ण रिकॉर्ड्स को संभालना- यह समझना कि नेस्टेड डेटा के लिए
copy()पर्याप्त क्यों नहीं है
पूर्वापेक्षाएँ: सेट — डुप्लिकेट्स के बिना एक संग्रह.
संरचना को पहचानना
orders = [
{"customer": "rafi", "item": "pen", "quantity": 3, "price": 15.0},
{"customer": "ahmed", "item": "bag", "quantity": 1, "price": 850.0},
]
print(len(orders))
print(orders[0])
print(orders[0]["customer"])
print(orders[1]["price"])2
{'customer': 'rafi', 'item': 'pen', 'quantity': 3, 'price': 15.0}
rafi
850.0पंक्ति orders[0]["customer"] इस अध्याय का मुख्य कौशल है, और इसे बाएं से दाएं, एक समय में एक कदम पढ़ा जाता है:
orders— एक लिस्टorders[0]— इसका पहला आइटम, जो एक डिक्शनरी हैorders[0]["customer"]— उस डिक्शनरी काcustomerमान
संदेह होने पर, रुकें और मध्यवर्ती चरण को प्रिंट करें। print(orders[0]) लिखकर यह देखना कि यह एक डिक्शनरी है, एक ऐसी आदत है जो नेस्टेड डेटा की आधी परेशानी दूर कर देती है।
इस पर लूप चलाना
orders = [
{"customer": "rafi", "item": "pen", "quantity": 3, "price": 15.0},
{"customer": "ahmed", "item": "bag", "quantity": 1, "price": 850.0},
]
for order in orders:
total = order["quantity"] * order["price"]
print(f"{order['customer']:<8} {order['item']:<6} {total:>8.2f}")rafi pen 45.00
ahmed bag 850.00for order in orders हर बार एक डिक्शनरी देता है, और इसके अंदर आप नाम से चीज़ों तक पहुँचते हैं। कहीं भी कोई इंडेक्स गणित नहीं है।
f-string के अंदर कोट्स: f"{order['customer']}" अंदर सिंगल कोट्स का उपयोग करता है क्योंकि f-string स्वयं डबल कोट्स के साथ लिखी गई है। अंदर और बाहर एक ही प्रकार का उपयोग करने पर पायथन यह नहीं बता सकता कि टेक्स्ट कहाँ समाप्त होता है। एक प्रकार अंदर रखें और दूसरा बाहर।अपूर्ण रिकॉर्ड्स
वास्तविक डेटा में, प्रत्येक रिकॉर्ड में प्रत्येक की (key) नहीं होती:
orders = [{"customer": "rafi"}]
print(orders[0]["discount"])KeyError: 'discount'KeyError कहता है कि की गायब है, लेकिन यह नहीं कि कौन से रिकॉर्ड में यह गायब है। जब बारह हज़ार में से किसी एक ऑर्डर में ऐसा होता है तो इसे खोजना मुश्किल होता है — यही कारण है कि enumerate के साथ लूप चलाना संख्या को हाथ में रखता है।
जब किसी की का अनुपस्थित होना सामान्य हो, तो .get():
orders = [{"customer": "rafi"}]
print(orders[0].get("discount", 0))0दूसरा रूप — डिक्शनरी के अंदर लिस्ट
by_customer = {
"rafi": ["pen", "ink"],
"ahmed": ["bag"],
}
by_customer["rafi"].append("bottle")
by_customer["dia"] = ["eraser"]
print(by_customer)
for customer, items in by_customer.items():
print(f"{customer}: {len(items)} item(s) - {', '.join(items)}"){'rafi': ['pen', 'ink', 'bottle'], 'ahmed': ['bag'], 'dia': ['eraser']}
rafi: 3 item(s) - pen, ink, bottle
ahmed: 1 item(s) - bag
dia: 1 item(s) - eraserपंक्ति by_customer["rafi"].append("bottle") वास्तव में दो कदम हैं: by_customer["rafi"] एक सूची निकालता है, और फिर append उस सूची में जोड़ता है।
यह रूप अध्याय 15 की एक समस्या का उत्तर देता है, जहाँ एक की केवल एक बार मौजूद हो सकती थी। मान को एक सूची बनाएं और वे एक से अधिक रिकॉर्ड रख सकते हैं।
समूहीकरण (Grouping) — सबसे उपयोगी पैटर्न
डिक्शनरी की एक सूची को "किसने क्या खरीदा" में बदलना:
orders = [
{"customer": "rafi", "item": "pen"},
{"customer": "ahmed", "item": "bag"},
{"customer": "rafi", "item": "ink"},
]
grouped = {}
for order in orders:
customer = order["customer"]
if customer not in grouped:
grouped[customer] = []
grouped[customer].append(order["item"])
print(grouped){'rafi': ['pen', 'ink'], 'ahmed': ['bag']}बीच की तीन पंक्तियाँ पूरी तकनीक हैं: यदि की गायब है, तो पहले वहाँ एक खाली सूची रखें, फिर बिना किसी चिंता के append करें।
वही चीज़ एक पंक्ति में भी आ सकती है:
orders = [
{"customer": "rafi", "item": "pen"},
{"customer": "rafi", "item": "ink"},
]
grouped = {}
for order in orders:
grouped.setdefault(order["customer"], []).append(order["item"])
print(grouped){'rafi': ['pen', 'ink']}setdefault(key, []) कहता है "मुझे इस की का मान दें, और यदि इसमें कोई मान नहीं है तो वहाँ यह खाली सूची डालें और फिर मुझे वह दें" — और जो कुछ भी वापस आता है उसमें append कर दिया जाता है।
नेस्टेड डेटा के लिए copy() पर्याप्त नहीं है
अध्याय 12 ने दिखाया कि b = a एक ही सूची पर दो नाम छोड़ता है, और copy() इसका समाधान है। नेस्टेड डेटा के साथ, copy() केवल एक स्तर की सुरक्षा करता है:
import copy
template = {"name": "", "items": []}
a = template.copy()
b = copy.deepcopy(template)
a["items"].append("pen")
b["items"].append("bag")
print(template)
print(a)
print(b){'name': '', 'items': ['pen']}
{'name': '', 'items': ['pen']}
{'name': '', 'items': ['bag']}a को copy() के साथ बनाया गया था — एक नई बाहरी डिक्शनरी, लेकिन आंतरिक सूची वही मूल सूची है। इसलिए a["items"].append("pen") ने मूल template को भी बदल दिया।
b को deepcopy() के साथ बनाया गया था, जो अंदर की हर चीज़ की भी प्रतिलिपि बनाता है। इसलिए b में किए गए परिवर्तन कहीं और नहीं फैले।
एक संपूर्ण उदाहरण
orders.py:
# डेटा वास्तव में जिस रूप में आता है: रिकॉर्ड्स की एक सूची
orders = [
{"customer": "rafi", "item": "pen", "quantity": 3, "price": 15.0},
{"customer": "ahmed", "item": "bag", "quantity": 1, "price": 850.0},
{"customer": "rafi", "item": "ink", "quantity": 2, "price": 120.0},
{"customer": "dia", "item": "pen", "quantity": 5, "price": 15.0},
]
print("Customer Item Qty Total")
grand_total = 0.0
for order in orders:
total = order["quantity"] * order["price"]
grand_total = grand_total + total
print(f"{order['customer']:<9} {order['item']:<6} {order['quantity']:>3} {total:>10.2f}")
print(f"{'':<20}{grand_total:>10.2f}")
print()
# ग्राहक द्वारा खर्च को समूहीकृत करें
spend = {}
for order in orders:
customer = order["customer"]
spend[customer] = spend.get(customer, 0.0) + order["quantity"] * order["price"]
# टपल में राशि को पहले रखकर राशि के अनुसार सॉर्ट करें
pairs = []
for customer, amount in spend.items():
pairs.append((amount, customer))
pairs.sort(reverse=True)
print("Spend per customer, highest first:")
for amount, customer in pairs:
print(f" {customer:<8} {amount:>8.2f}")
distinct = set()
for order in orders:
distinct.add(order["item"])
print()
print("Distinct items:", sorted(distinct))
print("Best customer :", pairs[0][1])Customer Item Qty Total
rafi pen 3 45.00
ahmed bag 1 850.00
rafi ink 2 240.00
dia pen 5 75.00
1210.00
Spend per customer, highest first:
ahmed 850.00
rafi 285.00
dia 75.00
Distinct items: ['bag', 'ink', 'pen']
Best customer : ahmedयह छोटा प्रोग्राम पिछले चार अध्यायों के प्रत्येक कंटेनर का उपयोग करता है, प्रत्येक को ठीक उसी स्थान पर जहाँ वह होना चाहिए।
एक लिस्ट ऑर्डर्स के लिए, क्योंकि संख्या अज्ञात है और क्रम मायने रखता है।
डिक्शनरी प्रत्येक ऑर्डर के लिए, क्योंकि हर हिस्से को एक नाम चाहिए; और spend के लिए, क्योंकि यह नाम से संचय करता है।
टपल pairs में प्रत्येक जोड़ी के लिए। राशि को टपल में पहले रखा गया है, क्योंकि पायथन टपल को उनके पहले मान के आधार पर सॉर्ट करता है।
एक सेट distinct के लिए, क्योंकि सवाल था "कितने अलग-अलग"।
जब यह टूटता है
KeyError: 'discount' — लेकिन किस रिकॉर्ड में? for i, order in enumerate(orders): के साथ लूप चलाएं ताकि विफल होने पर i ज्ञात हो।
TypeError: string indices must be integers लगभग हमेशा इसका मतलब है कि आपने सोचा था कि आपके पास एक डिक्शनरी है जबकि आपके पास एक स्ट्रिंग है। print(type(order)) से जाँचें।
TypeError: list indices must be integers or slices, not str विपरीत गलती — आपके पास एक सूची है और आप नाम से पूछ रहे हैं। आमतौर पर एक [0] छूट गया है: orders[0]["customer"], न कि orders["customer"]।
मैंने एक प्रतिलिपि बदली और मूल भी बदल गया copy() उथला (shallow) है — आंतरिक सूचियाँ और डिक्शनरी साझा रहती हैं। import copy करें और copy.deepcopy(...) का उपयोग करें।
चरण 4 / 6 — अनुमान
अपनी समझ की जाँच करें
Two levels deep. What is printed?
orders = [
{"customer": "rafi", "item": "pen"},
{"customer": "ahmed", "item": "bag"},
]
print(orders[1]["item"])- Abag
- Bpen
- Cahmed
- DA `KeyError`
An attempt to group. What happens on the very first pass?
orders = [
{"customer": "rafi", "item": "pen"},
]
grouped = {}
for order in orders:
grouped[order["customer"]].append(order["item"])
print(grouped)- A`KeyError: 'rafi'` — the key does not exist yet, so there is nothing to append to
- BIt works and prints `{'rafi': ['pen']}`
- CAn `AttributeError` — a dictionary has no `append`
- DIt prints `{}`
A copy() was taken and two changes made to it. What happened to the original?
import copy
template = {"name": "", "items": []}
a = template.copy()
a["name"] = "rafi"
a["items"].append("pen")
print(template)- A{'name': '', 'items': ['pen']}
- B{'name': '', 'items': []}
- C{'name': 'rafi', 'items': ['pen']}
- D{'name': 'rafi', 'items': []}
उत्तर देने के लिए अकाउंट आवश्यक है
अपने उत्तर जाँचने के लिए साइन इन करें
प्रश्न ऊपर दिए गए हैं, और मन में उत्तर सोचना ही मुख्य कार्य है। सही उत्तर, व्याख्या और तीन-स्तरीय संकेत देखने के लिए साइन इन करें।
आपकी बारी
कम से कम छह किताबों की एक सूची वाली library.py नामक फ़ाइल लिखें, जिनमें से प्रत्येक एक शीर्षक (title), एक लेखक (author), एक वर्ष (year) और प्रतियों की संख्या (copies) वाली डिक्शनरी हो।
फिर:
- प्रत्येक किताब को संरेखित कॉलम में प्रिंट करें
- कुल प्रतियों और औसत वर्ष की गणना करें
- लेखक द्वारा
{"author": ["title", "title"]}में समूहीकृत करें और प्रिंट करें कि प्रत्येक के पास कितनी किताबें हैं - एक सेट के साथ विशिष्ट (distinct) लेखकों की गिनती करें
- सबसे अधिक प्रतियों वाली पुस्तक का शीर्षक प्रिंट करें
Step 6 of 6
चुनौती — the chapter quiz
सरल से कठिन — दस प्रश्न, अंतिम वाले जानबूझकर चुनौतीपूर्ण बनाए गए हैं।
Sign in to take the quiz