Kodax

Comprehensions — هياكل البيانات

Comprehensions

كثيراً ما نكتب حلقة هدفها الوحيد بناء قائمة جديدة من قائمة موجودة:

squares = []
for x in range(1, 6):
    squares.append(x ** 2)

الـ comprehension تكتب نفس الفكرة في سطر واحد مقروء:

squares = [x ** 2 for x in range(1, 6)]

البنية

[ التعبير for العنصر in المصدر if الشرط ]

اقرأها هكذا: "أعطني التعبير لكل عنصر في المصدر يحقق الشرط".

evens = [n for n in range(20) if n % 2 == 0]
names = [s.title() for s in ["sara", "ali"]]

if في المكانين

nums = [4, -2, 7, -1]
[x for x in nums if x > 0]                 # تصفية: if في النهاية
["موجب" if x > 0 else "سالب" for x in nums]  # اختيار قيمة: if-else في البداية

التصفية تحذف عناصر، أما if-else في البداية فتنتج عنصراً لكل عنصر.

أنواع أخرى

words = ["Python", "code", "python"]
{n: n ** 2 for n in range(5)}          # قاموس
{w.lower() for w in words}             # مجموعة
sum(x ** 2 for x in range(1000))       # تعبير مولّد (generator)

تعبير المولّد بين أقواس عادية لا ينشئ القائمة في الذاكرة، بل ينتج القيم واحدة واحدة، لذلك هو الأنسب مع sum و max و any على بيانات كبيرة.

الحلقات المتداخلة

matrix = [[1, 2], [3, 4]]
pairs = [(x, y) for x in range(3) for y in range(3) if x != y]
flat = [n for row in matrix for n in row]

الترتيب مثل الحلقات العادية: الأولى هي الخارجية.

متى لا تستخدمها؟

- إذا احتجت أكثر من شرط وتحويل معقد، الحلقة العادية أوضح.

- إذا كان الهدف تنفيذ فعل (طباعة، حفظ) وليس بناء قائمة، استخدم حلقة: [print(x) for x in items] أسلوب سيئ.

تمرين

من قائمة قواميس طلاب {"name", "score"}: أنشئ قائمة بأسماء الناجحين (≥ 50)، وقاموساً {الاسم: التقدير}، ومجموعة بالدرجات المختلفة.

# List Comprehension الأساسية
squares = [x**2 for x in range(1, 6)]
print(squares)  # [1, 4, 9, 16, 25]

# مع شرط
evens = [x for x in range(10) if x % 2 == 0]
print(evens)  # [0, 2, 4, 6, 8]

# مع تحويل
names = ["ahmed", "mohammed", "ali"]
upper_names = [name.upper() for name in names]
print(upper_names)  # ['AHMED', 'MOHAMMED', 'ALI']

# Nested loops
matrix = [[1, 2], [3, 4], [5, 6]]
flat = [num for row in matrix for num in row]
print(flat)  # [1, 2, 3, 4, 5, 6]

# مع if-else
labels = ["زوجي" if x % 2 == 0 else "فردي" for x in range(5)]
print(labels)  # ['زوجي', 'فردي', 'زوجي', 'فردي', 'زوجي']

# Dict Comprehension
nums = [1, 2, 3, 4, 5]
squares_dict = {n: n**2 for n in nums}
print(squares_dict)  # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

# عكس قاموس
original = {'a': 1, 'b': 2, 'c': 3}
flipped = {v: k for k, v in original.items()}
print(flipped)  # {1: 'a', 2: 'b', 3: 'c'}

# Set Comprehension
text = "hello world"
unique_letters = {char for char in text if char.isalpha()}
print(unique_letters)  # {'h', 'e', 'l', 'o', 'w', 'r', 'd'}

# Generator Expression (توفير الذاكرة)
sum_squares = sum(x**2 for x in range(1000000))

# مقارنة الذاكرة
import sys
list_comp = [x**2 for x in range(1000)]
gen_exp = (x**2 for x in range(1000))
print(f"List: {sys.getsizeof(list_comp)} bytes")
print(f"Generator: {sys.getsizeof(gen_exp)} bytes")

# تطبيق عملي: تصفية بيانات
students = [
    {"name": "أحمد", "score": 85},
    {"name": "محمد", "score": 45},
    {"name": "علي", "score": 92},
]
passed = [s["name"] for s in students if s["score"] >= 60]
print(passed)  # ['أحمد', 'علي']
اختبر فهمك