إذا كنت تعرف أن max() تعيد أكبر رقم وأن min() تعيد أصغر رقم، فقد وصلت إلى الخطوة التالية: ماذا لو كانت عناصر القائمة قواميس أو tuples أو نصوصًا، وتريد المقارنة حسب سعر أو درجة أو طول معيّن؟ هنا نستخدم المعامل key=.
في هذا المقال من بايثون العرب سنستخدم max() وmin() مع key لاختيار العنصر الكامل حسب معيار مخصص، مثل أعلى price في List of Dictionaries أو أعلى score أو أطول نص.
أما إذا كان هدفك فقط إيجاد أكبر وأصغر رقم عادي في قائمة، فراجع المقال المتخصص: إيجاد أكبر وأصغر رقم في قائمة Python.
{getToc} $title={محتوى المقال}
{alertInfo} الفكرة الأساسية:keyلا تغيّر العنصر الذي تعيدهmax()أوmin()؛ بل تحدد فقط القيمة التي ستستخدمها Python للمقارنة بين العناصر.
ما وظيفة key في max و min؟
الصيغة العامة هي:
max(items, key=function)
min(items, key=function)
تأخذ Python كل عنصر، تمرره إلى دالة key للحصول على قيمة المقارنة، ثم تعيد العنصر الأصلي صاحب أكبر أو أصغر قيمة.
مثلًا، لاختيار أطول كلمة بدل الترتيب الأبجدي:
words = ["AI", "Python", "programming", "web"]
longest = max(words, key=len)
shortest = min(words, key=len)
print(longest)
print(shortest)
programming
AI
لاحظ أن key=len استخدمت طول كل كلمة للمقارنة، لكن max() أعادت الكلمة نفسها وليس رقم طولها.
أكبر عنصر في List of Dictionaries حسب price
هذه من أهم الحالات العملية. لنفترض أن لدينا منتجات، وكل منتج عبارة عن dict:
products = [
{"name": "Laptop", "price": 1200},
{"name": "Phone", "price": 800},
{"name": "Tablet", "price": 450}
]
most_expensive = max(
products,
key=lambda item: item["price"]
)
print(most_expensive)
{'name': 'Laptop', 'price': 1200}
التعبير lambda item: item["price"] يقول لـPython: عند مقارنة كل قاموس، استخدم قيمة price. والنتيجة هي القاموس الكامل للمنتج الأعلى سعرًا.
أصغر عنصر حسب price
نستخدم نفس الفكرة مع min():
cheapest = min(
products,
key=lambda item: item["price"]
)
print(cheapest)
{'name': 'Tablet', 'price': 450}
إيجاد أعلى score في List of Dictionaries
لا يقتصر الأمر على الأسعار. إذا كانت لديك قائمة طلاب مثلًا:
students = [
{"name": "Ali", "score": 88},
{"name": "Sara", "score": 96},
{"name": "Omar", "score": 91}
]
top_student = max(
students,
key=lambda student: student["score"]
)
print(top_student["name"])
print(top_student["score"])
Sara
96
{alertSuccess}
إذا أردت العنصر الكامل صاحب أعلى قيمة، استخدم max(list, key=...). لا تنشئ قائمة منفصلة من القيم إلا إذا كنت تحتاج القيم نفسها لسبب آخر.
هل تريد العنصر الكامل أم أكبر قيمة فقط؟
هناك فرق مهم بين استخراج القيمة القصوى واستخراج العنصر الذي يحملها. إذا كتبت:
highest_price = max(
item["price"]
for item in products
)
print(highest_price)
1200
ستحصل على السعر فقط. أما max(products, key=lambda item: item["price"]) فتعيد قاموس المنتج كاملًا، وهذا أفضل عندما تحتاج الاسم والسعر وبقية بيانات العنصر.
إذا كان لديك Dictionary واحد بدل List of Dictionaries
إذا كانت البيانات بهذا الشكل {"Ali": 88, "Sara": 96} وتريد الاسم صاحب أعلى قيمة، يمكنك تمرير الدالة dict.get إلى key:
scores = {
"Ali": 88,
"Sara": 96,
"Omar": 91
}
best_name = max(
scores,
key=scores.get
)
print(best_name)
هذه حالة مختلفة عن List of Dictionaries: هنا max() تمر على مفاتيح القاموس، وscores.get تعطيها القيمة المقابلة لكل مفتاح للمقارنة.
استخدام itemgetter بدل lambda
عندما يكون معيار المقارنة مجرد مفتاح داخل Dictionary أو موضع داخل Tuple، يمكنك استخدام operator.itemgetter() بدل كتابة lambda في كل مرة.
from operator import itemgetter
most_expensive = max(
products,
key=itemgetter("price")
)
print(most_expensive)
للمبتدئ، lambda غالبًا أوضح لأنها تعرض منطق المقارنة أمامك مباشرة. أما itemgetter() فهي بديل مختصر ومفيد عندما يتكرر نفس النمط.
استخدام max مع Tuple حسب العنصر الثاني
إذا كانت البيانات tuples مثل (name, score) وتريد المقارنة حسب الدرجة، فاستخدم العنصر ذي الفهرس 1:
results = [
("Ali", 78),
("Sara", 95),
("Omar", 86)
]
best = max(
results,
key=lambda item: item[1]
)
print(best)
('Sara', 95)
ما الفرق بين max مع key وبين sorted؟
إذا كنت تحتاج عنصرًا واحدًا فقط هو الأكبر أو الأصغر حسب معيار، استخدم max() أو min(). أما sorted() فتستخدمها عندما تحتاج ترتيب جميع العناصر.
| الحاجة | الأداة المناسبة | مثال |
|---|---|---|
| أعلى عنصر حسب score | max() |
max(students, key=lambda x: x["score"]) |
| أقل عنصر حسب price | min() |
min(products, key=lambda x: x["price"]) |
| ترتيب كل العناصر حسب score | sorted() |
sorted(students, key=lambda x: x["score"]) |
ماذا يحدث عند تساوي أكبر قيمة؟
إذا كان أكثر من عنصر يملك نفس قيمة key القصوى، فإن max() تعيد أول عنصر صادفته من العناصر المتساوية. وينطبق المبدأ نفسه على min().
players = [
{"name": "Ali", "score": 95},
{"name": "Sara", "score": 95},
{"name": "Omar", "score": 88}
]
winner = max(
players,
key=lambda player: player["score"]
)
print(winner["name"])
Ali
إذا كنت تريد جميع العناصر المتساوية
استخرج القيمة القصوى أولًا، ثم رشّح كل العناصر التي تحملها:
best_score = max(
players,
key=lambda player: player["score"]
)["score"]
leaders = [
player
for player in players
if player["score"] == best_score
]
print(leaders)
قاعدة كسر التعادل بمعيار ثانٍ
يمكن أن تعيد دالة key tuple. تقارن Python العنصر الأول، ثم تستخدم الثاني إذا حدث تعادل:
best_player = max(
players,
key=lambda player: (
player["score"],
player["name"]
)
)
استخدم معيارًا ثانيًا فقط عندما يكون له معنى حقيقي في بياناتك، لا لمجرد التخلص من التعادل.
ماذا لو كانت القائمة فارغة؟ استخدم default
استدعاء max([]) أو min([]) بدون عناصر يرفع ValueError. عند تمرير iterable واحد يمكنك تحديد قيمة default تعاد عند الفراغ:
products = []
result = max(
products,
key=lambda item: item["price"],
default=None
)
if result is None:
print("لا توجد منتجات")
{alertWarning} استخدمdefaultبقيمة تستطيع تمييزها بوضوح عن النتائج الطبيعية، مثلNoneعندما لا تكونNoneعنصرًا صالحًا في البيانات.
خطأ شائع: المفتاح غير موجود في بعض القواميس
هذا الكود يفترض أن كل عنصر يحتوي على price:
most_expensive = max(
products,
key=lambda item: item["price"]
)
إذا كان أحد القواميس بلا مفتاح price فسيظهر KeyError. الأفضل أن تكون بنية البيانات متسقة. ويمكن استخدام item.get("price", ...) فقط عندما تحدد بوضوح ما القيمة الافتراضية الصحيحة في مشروعك.
متى لا تحتاج إلى key؟
إذا كانت القائمة تحتوي على أرقام مباشرة وتريد أعلى أو أقل رقم فقط، فلا حاجة إلى key:
numbers = [15, 8, 22, 4]
print(max(numbers))
print(min(numbers))
شرح إيجاد أكبر وأصغر رقم عادي والحل اليدوي باستخدام for loop موجود بالفعل في
المقال الأساسي المتخصص، لذلك لا نكرره هنا.
جدول سريع لاختيار key المناسب
| نوع البيانات | المطلوب | key |
|---|---|---|
| نصوص | أطول نص | key=len |
| List of Dictionaries | أعلى سعر | key=lambda x: x["price"] |
| List of Dictionaries | أعلى درجة | key=lambda x: x["score"] |
| Tuples | أعلى قيمة في العنصر الثاني | key=lambda x: x[1] |
| Dictionary / Tuple متكرر | استخراج حقل مباشر | itemgetter(...) |
أسئلة شائعة عن max و min مع key
ما معنى key في max و min؟
هي دالة تأخذ كل عنصر وتعيد قيمة تستخدمها Python للمقارنة. النتيجة النهائية تبقى العنصر الأصلي.
كيف أجد أكبر Dictionary حسب قيمة معينة؟
مرر قائمة القواميس إلى max() واستخدم مثلًا key=lambda x: x["price"] للمقارنة حسب السعر.
هل lambda إلزامية مع key؟
لا. يمكنك تمرير دالة موجودة مثل len، أو دالة عادية كتبتها أنت، أو أدوات مثل operator.itemgetter().
ماذا يعيد max عند تساوي قيم key؟
يعيد أول عنصر صادفه من العناصر التي تملك القيمة القصوى نفسها. وإذا أردت كل العناصر المتساوية، استخرج القيمة القصوى ثم رشّح العناصر التي تحملها.
كيف أستخدم max مع قائمة فارغة؟
استخدم default عند تمرير iterable واحد، مثل max(items, key=..., default=None).
روابط مفيدة
- إيجاد أكبر وأصغر رقم في قائمة Python
- شرح Lists في Python للمبتدئين
- توثيق Python الرسمي لدالة max
- توثيق Python الرسمي لدالة min
- توثيق itemgetter في Python
الخلاصة
عندما تكون العناصر أرقامًا مباشرة، يكفي غالبًا max(numbers) وmin(numbers). أما عندما تكون البيانات مركبة، فإن key= هي الأداة التي تحدد بأي قيمة تتم المقارنة.
مع List of Dictionaries يمكنك المقارنة حسب price أو score باستخدام lambda أو itemgetter(). ومع النصوص تستطيع استخدام key=len، ومع tuples تستطيع المقارنة حسب موضع محدد.
{alertSuccess} القاعدة العملية: استخدمmax(..., key=...)أوmin(..., key=...)عندما تريد إرجاع العنصر الكامل، لكن المقارنة يجب أن تتم حسب خاصية محددة داخله.



