Dictionary و Set Comprehension: إنشاء القواامس والمجموعات بقوة وأناقة

في الفصل السابق، تعلمت كيفية استخدام List Comprehension لإنشاء قوائس بطريقة أنيقة وفعالة. الآن حان الوقت لاستكشاف Dictionary Comprehension و Set Comprehension! هذه الأدوات القوية تسمح لك بإنشاء قواامس ومجموعات معقدة بسطر واحد من الكود. سنتعلم كيفية تحويل البيانات، فلترتها، وإعادة تنظيمها بطرق احترافية.

1. أساسيات Dictionary Comprehension

Dictionary Comprehension توفر طريقة مختصرة لإنشاء قاموس جديد من البيانات الموجودة. الصيغة الأساسية:

dict_comprehension_basics.py
# الصيغة الأساسية:
# {key: value for item in iterable}

# مثال 1: إنشاء قاموس من أرقام
numbers = [1, 2, 3, 4, 5]
squares = {num: num ** 2 for num in numbers}
print(squares)
# النتيجة: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
النتيجة
{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

شرح الكود: نأخذ كل رقم من قائمة الأرقام، ونستخدمه كـ key والمربع كـ value. النتيجة: قاموس يربط كل رقم بمربعه.

مثال 2: تحويل قائمة إلى قاموس مع الطول
dict_word_lengths.py
# قائمة من الكلمات
words = ["مرحبا", "عالم", "بايثون", "برمجة"]

# إنشاء قاموس: الكلمة وطول الكلمة
word_lengths = {word: len(word) for word in words}
print(word_lengths)
# النتيجة: {'مرحبا': 5, 'عالم': 4, 'بايثون': 6, 'برمجة': 4}
النتيجة
{'مرحبا': 5, 'عالم': 4, 'بايثون': 6, 'برمجة': 4}

شرح الكود: لكل كلمة في القائمة، نستخدم الكلمة نفسها كـ key وطول الكلمة كـ value. هذا مفيد جداً لمعالجة النصوص.

مثال 3: الفرق بين Comprehension والطريقة التقليدية
dict_traditional_vs_comprehension.py
# الطريقة التقليدية - طويلة
cities = ["القاهرة", "الرياض", "دبي"]
cities_dict = {}
for city in cities:
    cities_dict[city] = len(city)
print(cities_dict)
# {'القاهرة': 6, 'الرياض': 6, 'دبي': 3}

# Dictionary Comprehension - أنيقة
cities = ["القاهرة", "الرياض", "دبي"]
cities_dict = {city: len(city) for city in cities}
print(cities_dict)
# {'القاهرة': 6, 'الرياض': 6, 'دبي': 3}
النتيجة
{'القاهرة': 6, 'الرياض': 6, 'دبي': 3} {'القاهرة': 6, 'الرياض': 6, 'دبي': 3}

شرح الكود: كل الطريقتين تعطي نفس النتيجة، لكن Dictionary Comprehension أقصر وأسهل قراءة. إنها طريقة "pythonic" (طريقة بايثونية احترافية).

2. Dictionary Comprehension مع الشروط

يمكنك إضافة شروط للفلترة أو تغيير القيم بناءً على شرط معين.

مثال 1: فلترة الأزواج الزوجية
dict_filter_evens.py
# قائمة أرقام
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# قاموس يحتوي فقط على الأرقام الزوجية ومربعاتها
evens = {num: num ** 2 for num in numbers if num % 2 == 0}
print(evens)
# النتيجة: {2: 4, 4: 16, 6: 36, 8: 64, 10: 100}
النتيجة
{2: 4, 4: 16, 6: 36, 8: 64, 10: 100}

شرح الكود: الشرط if num % 2 == 0 يتحقق ما إذا كان الرقم زوجي. فقط الأرقام الزوجية تُضاف إلى القاموس.

مثال 2: استخدام if-else لتعديل القيم
dict_ifelse_values.py
# قائمة درجات الطلاب
grades = [45, 75, 92, 55, 88, 40, 78]

# قاموس: الدرجة والحالة (نجح/راسب)
result = {grade: "نجح" if grade >= 60 else "راسب" for grade in grades}
print(result)
# النتيجة: {45: 'راسب', 75: 'نجح', 92: 'نجح', 55: 'راسب', 88: 'نجح', 40: 'راسب', 78: 'نجح'}
النتيجة
{45: 'راسب', 75: 'نجح', 92: 'نجح', 55: 'راسب', 88: 'نجح', 40: 'راسب', 78: 'نجح'}

شرح الكود: لكل درجة، نستخدم if-else للتحقق: إذا كانت الدرجة >= 60 تكون "نجح"، وإلا "راسب". كل الدرجات موجودة في القاموس.

مثال 3: فلترة وتحويل معاً
dict_filter_and_transform.py
# أسعار المنتجات
prices = {"تفاح": 10, "برتقال": 15, "موز": 5, "كيوي": 20}

# الحصول على المنتجات الغالية (أكثر من 10) برسم خصم 20%
discounted = {product: price * 0.8 for product, price in prices.items() 
              if price > 10}
print(discounted)
# النتيجة: {'برتقال': 12.0, 'كيوي': 16.0}
النتيجة
{'برتقال': 12.0, 'كيوي': 16.0}

شرح الكود: نستخدم .items() للحصول على key و value معاً. الشرط if price > 10 يفلتر فقط المنتجات الغالية، ثم نطبق الخصم (ضرب في 0.8).

3. تحويل البيانات بين الأنواع المختلفة

يمكنك تحويل قواامس إلى قواامس أخرى، أو من قائمة إلى قاموس.

مثال 1: عكس قاموس (مفاتيح وقيم)
dict_reverse.py
# قاموس: الدول والعواصم
capitals = {"مصر": "القاهرة", "السعودية": "الرياض", "الإمارات": "دبي"}

# عكس القاموس: العواصم والدول
reversed_dict = {value: key for key, value in capitals.items()}
print(reversed_dict)
# النتيجة: {'القاهرة': 'مصر', 'الرياض': 'السعودية', 'دبي': 'الإمارات'}
النتيجة
{'القاهرة': 'مصر', 'الرياض': 'السعودية', 'دبي': 'الإمارات'}

شرح الكود: نستبدل المفاتيح بالقيم والقيم بالمفاتيح. الآن بدلاً من البحث عن العاصمة من الدولة، نبحث عن الدولة من العاصمة.

مثال 2: تحويل قائمة أزواج إلى قاموس
dict_from_pairs.py
# قائمة من الأزواج
students_data = [("أحمد", 85), ("فاطمة", 92), ("محمد", 78)]

# تحويل إلى قاموس
students = {name: grade for name, grade in students_data}
print(students)
# النتيجة: {'أحمد': 85, 'فاطمة': 92, 'محمد': 78}
النتيجة
{'أحمد': 85, 'فاطمة': 92, 'محمد': 78}

شرح الكود: لكل زوج في القائمة، نستخرج الاسم (name) والدرجة (grade) ونحولهما إلى key و value في القاموس.

مثال 3: دمج قاموسين
dict_merge.py
# قاموسين منفصلين
dict1 = {"a": 1, "b": 2}
dict2 = {"c": 3, "d": 4}

# دمج الاثنين
merged = {**dict1, **dict2}
print(merged)
# النتيجة: {'a': 1, 'b': 2, 'c': 3, 'd': 4}

# أو باستخدام comprehension
merged2 = {k: v for d in [dict1, dict2] for k, v in d.items()}
print(merged2)
# النتيجة: {'a': 1, 'b': 2, 'c': 3, 'd': 4}
النتيجة
{'a': 1, 'b': 2, 'c': 3, 'd': 4} {'a': 1, 'b': 2, 'c': 3, 'd': 4}

شرح الكود: الطريقة الأولى استخدمنا ** (unpacking) لدمج القاموسين. الطريقة الثانية استخدمنا comprehension مع حلقتين متداخلتين للحصول على جميع key-value من القاموسين.

4. Set Comprehension (مجموعات برمجية)

Set Comprehension تعمل مثل List و Dictionary Comprehension، لكن النتيجة مجموعة (Set) التي لا تحتوي على عناصر مكررة.

الصيغة الأساسية:
set_comprehension_basics.py
# الصيغة الأساسية:
# {expression for item in iterable}

# مثال 1: إزالة العناصر المكررة
numbers = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
unique = {num for num in numbers}
print(unique)
# النتيجة: {1, 2, 3, 4} - تلقائياً تمت إزالة المكررات

# مثال 2: مربع الأرقام
numbers = [1, 2, 3, 4, 5]
squares = {num ** 2 for num in numbers}
print(squares)
# النتيجة: {1, 4, 9, 16, 25}
النتيجة
{1, 2, 3, 4} {1, 4, 9, 16, 25}

شرح الكود: المجموعة (Set) تحتفظ فقط بالعناصر الفريدة. عندما أضفنا الأرقام المكررة، تمت إزالتها تلقائياً. الترتيب في المجموعة ليس مهماً.

مثال: فلترة وإزالة التكرارات معاً
set_filter_unique.py
# قائمة بأحرف مكررة
letters = ['أ', 'ب', 'أ', 'ج', 'ب', 'د', 'أ', 'ج']

# الحروف الفريدة
unique_letters = {letter for letter in letters}
print(unique_letters)
# النتيجة: {'أ', 'ب', 'ج', 'د'}

# الأرقام الزوجية الفريدة من قائمة مع تكرارات
numbers = [2, 4, 4, 6, 8, 8, 10, 2, 4]
even_unique = {num for num in numbers if num % 2 == 0}
print(even_unique)
# النتيجة: {2, 4, 6, 8, 10}
النتيجة
{'أ', 'ب', 'ج', 'د'} {2, 4, 6, 8, 10}

شرح الكود: في المثال الأول، حتى مع وجود 'أ' و'ب' و'ج' مكررة، المجموعة احتفظت بنسخة واحدة فقط. في المثال الثاني، فلترنا الأرقام الزوجية فقط وأزلنا التكرارات.

مثال: العمليات الرياضية على المجموعات
set_operations.py
# مجموعتان من الأرقام
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}

# الاتحاد (Union) - جميع العناصر
union = set1 | set2
print(f"الاتحاد: {union}")
# النتيجة: {1, 2, 3, 4, 5, 6, 7, 8}

# التقاطع (Intersection) - العناصر المشتركة
intersection = set1 & set2
print(f"التقاطع: {intersection}")
# النتيجة: {4, 5}

# الفرق (Difference) - العناصر الموجودة في set1 فقط
difference = set1 - set2
print(f"الفرق: {difference}")
# النتيجة: {1, 2, 3}
النتيجة
الاتحاد: {1, 2, 3, 4, 5, 6, 7, 8} التقاطع: {4, 5} الفرق: {1, 2, 3}

شرح الكود: المجموعات تدعم عمليات رياضية: الاتحاد (|) يجمع كل العناصر، التقاطع (&) يأخذ العناصر المشتركة فقط، الفرق (-) يأخذ العناصر الموجودة في الأولى فقط.

5. أمثلة عملية متقدمة

مثال 1: معالجة بيانات الطلاب المتقدمة
advanced_students.py
# بيانات الطلاب
students = [
    {"id": 1, "name": "أحمد", "grades": [85, 90, 88]},
    {"id": 2, "name": "فاطمة", "grades": [92, 95, 90]},
    {"id": 3, "name": "محمد", "grades": [78, 80, 75]},
    {"id": 4, "name": "سارة", "grades": [88, 92, 90]}
]

# قاموس: الاسم والمعدل
averages = {s["name"]: sum(s["grades"]) / len(s["grades"]) 
            for s in students}
print("المعدلات:")
for name, avg in averages.items():
    print(f"{name}: {avg:.2f}")

# النتيجة:
# أحمد: 87.67
# فاطمة: 92.33
# محمد: 77.67
# سارة: 90.00

# تصفية: الطلاب ذو المعدل العالي (>85)
high_achievers = {s["name"]: sum(s["grades"]) / len(s["grades"]) 
                  for s in students 
                  if sum(s["grades"]) / len(s["grades"]) > 85}
print("\nالطلاب المتفوقون (>85):")
print(high_achievers)
# النتيجة: {'أحمد': 87.66..., 'فاطمة': 92.33..., 'سارة': 90.0}
النتيجة
المعدلات: أحمد: 87.67 فاطمة: 92.33 محمد: 77.67 سارة: 90.00 الطلاب المتفوقون (>85): {'أحمد': 87.67, 'فاطمة': 92.33, 'سارة': 90.0}

شرح الكود: في المثال الأول، نحسب متوسط درجات كل طالب باستخدام sum() / len(). في المثال الثاني، نضيف شرط للتصفية: فقط الطلاب الذين معدلهم > 85.

مثال 2: معالجة المنتجات والأسعار
products_pricing.py
# المنتجات والأسعار والكمية
inventory = [
    {"name": "تفاح", "price": 10, "quantity": 50},
    {"name": "برتقال", "price": 15, "quantity": 30},
    {"name": "موز", "price": 5, "quantity": 100},
    {"name": "كيوي", "price": 20, "quantity": 20}
]

# قاموس: المنتج والقيمة الإجمالية (price * quantity)
total_value = {item["name"]: item["price"] * item["quantity"] 
               for item in inventory}
print("القيمة الإجمالية لكل منتج:")
for product, value in total_value.items():
    print(f"{product}: {value}")

# النتيجة:
# تفاح: 500
# برتقال: 450
# موز: 500
# كيوي: 400

# تصفية: المنتجات التي قيمتها > 450
high_value = {item["name"]: item["price"] * item["quantity"] 
              for item in inventory 
              if item["price"] * item["quantity"] > 450}
print("\nالمنتجات ذات القيمة العالية:")
print(high_value)
# النتيجة: {'تفاح': 500, 'موز': 500}
النتيجة
القيمة الإجمالية لكل منتج: تفاح: 500 برتقال: 450 موز: 500 كيوي: 400 المنتجات ذات القيمة العالية: {'تفاح': 500, 'موز': 500}

شرح الكود: نحسب القيمة الإجمالية لكل منتج بضرب السعر في الكمية. ثم نفلتر فقط المنتجات ذات القيمة > 450.

مثال 3: تحليل النصوص والكلمات الفريدة
text_analysis.py
# النصوص
text = "بايثون هي لغة برمجية قوية وسهلة التعلم بايثون تستخدم في التطبيقات المختلفة"
words = text.split()

print(f"إجمالي الكلمات: {len(words)}")
# النتيجة: إجمالي الكلمات: 13

# الكلمات الفريدة (بدون تكرار)
unique_words = {word for word in words}
print(f"الكلمات الفريدة: {len(unique_words)}")
print(f"القائمة: {unique_words}")
# النتيجة:
# الكلمات الفريدة: 9
# القائمة: {'قوية', 'هي', 'بايثون', 'التعلم', 'لغة', 'التطبيقات', 'سهلة', 'وتستخدم', 'برمجية'}

# الكلمات الطويلة (أكثر من 4 حروف)
long_words = {word for word in words if len(word) > 4}
print(f"\nالكلمات الطويلة: {long_words}")
# النتيجة: {'بايثون', 'برمجية', 'قوية', 'التعلم', 'التطبيقات', 'المختلفة', 'تستخدم'}

# قاموس: الكلمة وطولها (الكلمات الفريدة فقط)
word_lengths = {word: len(word) for word in unique_words}
print(f"\nطول كل كلمة: {word_lengths}")
# النتيجة: {'قوية': 5, 'هي': 2, 'بايثون': 6, ...}
النتيجة
إجمالي الكلمات: 13 الكلمات الفريدة: 9 القائمة: {'قوية', 'هي', 'بايثون', 'التعلم', 'لغة', 'التطبيقات', 'سهلة', 'وتستخدم', 'برمجية'} الكلمات الطويلة: {'بايثون', 'برمجية', 'قوية', 'التعلم', 'التطبيقات', 'المختلفة', 'تستخدم'} طول كل كلمة: {'قوية': 5, 'هي': 2, 'بايثون': 6, 'التعلم': 6, ...}

شرح الكود: نقسم النص إلى كلمات. ثم نحصل على الكلمات الفريدة باستخدام Set Comprehension، وننشئ قاموس يربط كل كلمة بطولها.

6. مقارنة الأداء والطرق

مثال: Dictionary Comprehension vs الطرق التقليدية
performance_comparison.py
import time

# البيانات
numbers = list(range(1000000))

# الطريقة التقليدية
start = time.time()
result1 = {}
for num in numbers:
    if num % 2 == 0:
        result1[num] = num ** 2
time1 = time.time() - start

# Dictionary Comprehension
start = time.time()
result2 = {num: num ** 2 for num in numbers if num % 2 == 0}
time2 = time.time() - start

print(f"الطريقة التقليدية: {time1:.4f} ثانية")
print(f"Dictionary Comprehension: {time2:.4f} ثانية")
print(f"الفرق: {time1/time2:.2f}x أسرع")
النتيجة (تقريبية)
الطريقة التقليدية: 0.0856 ثانية Dictionary Comprehension: 0.0423 ثانية الفرق: 2.02x أسرع

شرح الكود: Dictionary Comprehension أسرع بحوالي مرتين من الطريقة التقليدية. هذا يجعلها اختياراً ممتازاً للبيانات الكبيرة.

جدول مقارنة الطرق الثلاث
النوع النتيجة الصيغة الاستخدام
List Comprehension قائمة [1, 2, 3] [x for x in data] إنشاء قوائس
Dictionary Comprehension قاموس {1: 2} {k: v for k, v in data} إنشاء قواامس
Set Comprehension مجموعة {1, 2} {x for x in data} إنشاء مجموعات فريدة

7. الأخطاء الشائعة

الخطأ 1: استخدام [] بدلاً من {} في Dictionary Comprehension
error_brackets.py
# الخطأ: استخدام []
# result = [num: num ** 2 for num in range(5)]  # SyntaxError

# الصحيح: استخدام {}
result = {num: num ** 2 for num in range(5)}
print(result)  # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
النتيجة
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
الخطأ 2: نسيان الفاصلة بين key و value
error_colon.py
# الخطأ: نسيان الفاصلة
# result = {num num ** 2 for num in range(5)}  # SyntaxError

# الصحيح: استخدام :
result = {num: num ** 2 for num in range(5)}
print(result)  # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
النتيجة
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
الخطأ 3: الخلط بين Set و List Comprehension
error_set_vs_list.py
# List Comprehension - الترتيب مهم، التكرار محفوظ
numbers = [1, 2, 2, 3]
list_result = [x for x in numbers]
print(f"List: {list_result}")  # [1, 2, 2, 3]

# Set Comprehension - بدون ترتيب، بدون تكرار
set_result = {x for x in numbers}
print(f"Set: {set_result}")  # {1, 2, 3}
النتيجة
List: [1, 2, 2, 3] Set: {1, 2, 3}
الخطأ 4: استخدام .items() بشكل خاطئ
error_items.py
# القاموس الأصلي
data = {"a": 1, "b": 2, "c": 3}

# الخطأ: نسيان .items()
# result = {k: v*2 for k, v in data}  # ValueError: too many values to unpack

# الصحيح: استخدام .items()
result = {k: v*2 for k, v in data.items()}
print(result)  # {'a': 2, 'b': 4, 'c': 6}
النتيجة
{'a': 2, 'b': 4, 'c': 6}

8. نصائح مهمة وأفضل الممارسات

  • استخدم {} مع : للقواامس: {key: value for ...} ليس {key value for ...}
  • استخدم {} بدون : للمجموعات: {value for ...} ليس {: value for ...}
  • تذكر .items() عند التكرار على القاموس: إذا كنت تحتاج الـ key و value معاً
  • Set comprehension إذا كنت تريد عناصر فريدة: بدلاً من list comprehension والتحويل لاحقاً
  • قاموس للبحث السريع: أسرع من البحث في قائمة (O(1) vs O(n))
  • الوضوح أولاً: إذا كانت comprehension معقدة جداً، استخدم حلقة عادية
مثال: اختيار الأداة الصحيحة
choosing_tool.py
# مثال: قائمة الأرقام
numbers = [1, 2, 3, 4, 5, 2, 3, 4]

# إذا أردت قائمة محفوظة الترتيب مع التكرارات:
# استخدم List Comprehension
result1 = [x ** 2 for x in numbers]
print(f"List: {result1}")  # [1, 4, 9, 16, 25, 4, 9, 16]

# إذا أردت أرقام فريدة بدون ترتيب محدد:
# استخدم Set Comprehension
result2 = {x ** 2 for x in numbers}
print(f"Set: {result2}")  # {1, 4, 9, 16, 25}

# إذا أردت البحث السريع (key-value):
# استخدم Dictionary Comprehension
result3 = {x: x ** 2 for x in numbers}
print(f"Dict: {result3}")  # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
النتيجة
List: [1, 4, 9, 16, 25, 4, 9, 16] Set: {1, 4, 9, 16, 25} Dict: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

شرح الكود: اختيار الأداة الصحيحة يعتمد على ما تحتاج: - List: للحفاظ على الترتيب والتكرارات - Set: للعناصر الفريدة - Dict: للبحث السريع عن key معين

9. تمرين عملي شامل

قم بكتابة برنامج يقوم بالمهام التالية:

  1. أنشئ قائمة من أسماء الطلاب وعلاماتهم: [("أحمد", 85), ("فاطمة", 92), ("محمد", 78), ("سارة", 88)]
  2. حول القائمة إلى قاموس باستخدام Dictionary Comprehension
  3. أنشئ قاموس آخر يحتوي على الطلاب الناجحين فقط (علامة > 80)
  4. أنشئ مجموعة من جميع العلامات الفريدة
  5. أنشئ قاموس: الطالب والتقييم ("ممتاز" إذا > 90، "جيد" إذا > 80، "يحتاج تحسين" غير ذلك)

تفكر متقدم: كيف يمكن دمج هذه العمليات لإنشاء قاموس متعمق يحتوي على جميع المعلومات المطلوبة؟

الخلاصة والانتقال إلى الفصل التالي

لقد تعلمت اليوم:

  • أساسيات Dictionary Comprehension وكيفية إنشاء القواامس بشكل أنيق
  • كيفية استخدام الشروط لفلترة والقيم وتعديلها
  • تحويل البيانات بين الأنواع المختلفة (عكس قاموس، دمج قواامس، إلخ)
  • Set Comprehension وكيفية استخدام المجموعات للعناصر الفريدة
  • العمليات الرياضية على المجموعات (اتحاد، تقاطع، فرق)
  • أمثلة عملية واقعية ومتقدمة
  • الفرق بين List و Dictionary و Set Comprehension

في الفصل التالي، ستتعلم عن معالجة النصوص والـ Strings. ستتمكن من التعامل مع النصوص بشكل متقدم، تقسيمها، دمجها، وتحليلها بطرق قوية وفعالة.

المحرر الذكي

اكتب الكود وشاهد النتيجة فوراً

جرب الآن مجاناً
قناة ديف عربي

تابع أحدث الدروس والتحديثات مباشرة على واتساب

انضم الآن