Kodax

الترتيب والبحث: 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
اختبر فهمك