الترتيب والبحث: sorted و key و zip و enumerate — هياكل البيانات
الترتيب والبحث في البيانات
البيانات الحقيقية نادراً ما تكون أرقاماً بسيطة: قائمة طلاب بدرجاتهم، منتجات بأسعارها. نحتاج أن نرتبها حسب معيار نختاره، ونمر على أكثر من قائمة معاً.
sort مقابل sorted
nums = [5, 2, 9]
nums.sort() # تعدّل القائمة نفسها وترجع None
new = sorted(nums) # ترجع قائمة جديدة وتترك الأصلsorted تعمل مع أي مصدر (tuple، مجموعة، مفاتيح قاموس) وترجع دائماً قائمة. ولكليهما reverse=True.
الترتيب بمفتاح: key
key دالة تُطبَّق على كل عنصر، ويُرتَّب حسب ناتجها:
words = ["قلم", "كتاب", "ممحاة"]
sorted(words, key=len) # حسب الطول
students = [("منى", 95), ("علي", 72), ("زيد", 88)]
def by_score(student):
return student[1]
sorted(students, key=by_score, reverse=True)lambda: دالة صغيرة في مكانها
بدلاً من تعريف by_score لاستخدام واحد:
sorted(students, key=lambda s: s[1], reverse=True)lambda s: s[1] تعني دالة تأخذ s وترجع s[1]. استخدمها للتعابير القصيرة فقط.
الترتيب بأكثر من معيار
أرجع tuple من key: يُرتب بالأول ثم بالثاني عند التساوي.
people = [{"name": "منى", "city": "بغداد"}, {"name": "علي", "city": "البصرة"}]
students = [("منى", 95), ("علي", 72)]
sorted(people, key=lambda p: (p["city"], p["name"]))
sorted(students, key=lambda s: (-s[1], s[0])) # الدرجة تنازلياً ثم الاسم أبجدياًmin و max بمفتاح
best = max(students, key=lambda s: s[1]) # الطالب صاحب أعلى درجة كاملاًenumerate و zip
sorted_students = [("منى", 95), ("زيد", 88)]
for rank, (name, score) in enumerate(sorted_students, start=1):
print(rank, name, score)
names = ["منى", "علي"]
scores = [95, 72]
for name, score in zip(names, scores):
print(name, score)
grades = dict(zip(names, scores)) # {'منى': 95, 'علي': 72}zip تتوقف عند أقصر قائمة.
any و all
scores = [95, 72, 88]
any(s >= 90 for s in scores) # هل يوجد طالب ممتاز؟
all(s >= 50 for s in scores) # هل نجح الجميع؟ترتيب قاموس
prices = {"قهوة": 3, "شاي": 1, "عصير": 4}
sorted(prices.items(), key=lambda item: item[1])تمرين
لديك قائمة منتجات (اسم، سعر، كمية). اطبعها مرتبة حسب القيمة الإجمالية (السعر × الكمية) تنازلياً مع ترقيم، واطبع أرخص منتج، وتحقق إن كانت كل الكميات أكبر من صفر.
students = [("منى", 95), ("علي", 72), ("زيد", 88), ("سارة", 95)]
# sorted ترجع قائمة جديدة
print(sorted([5, 2, 9, 1]))
print(sorted(["قلم", "كتاب", "ممحاة"], key=len))
# الترتيب بالدرجة تنازلياً، ثم بالاسم عند التساوي
ranked = sorted(students, key=lambda s: (-s[1], s[0]))
for rank, (name, score) in enumerate(ranked, start=1):
print(f"{rank}. {name:<6} {score}")
# min/max بمفتاح ترجع العنصر كاملاً
print("الأعلى:", max(students, key=lambda s: s[1]))
print("الأقل:", min(students, key=lambda s: s[1]))
# zip لدمج قائمتين
names = ["قهوة", "شاي", "عصير"]
prices = [3.5, 1.25, 4.0]
menu = dict(zip(names, prices))
print(menu)
# ترتيب قاموس حسب القيم
for item, price in sorted(menu.items(), key=lambda kv: kv[1]):
print(f"{item}: {price}")
# any / all
scores = [s for _, s in students]
print("يوجد ممتاز:", any(s >= 90 for s in scores))
print("نجح الجميع:", all(s >= 50 for s in scores))
# sort تعدّل القائمة وترجع None
values = [3, 1, 2]
result = values.sort()
print(values, result) # [1, 2, 3] None
اختبر فهمك