0%
هياكل البيانات في Python: القوائم، والصفوف، والقواميس، والمجموعات

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

نظّم بياناتك وعالجها بكفاءة

10-15 دقيقة

هياكل البيانات في Python: القوائم، والصفوف، والقواميس، والمجموعات

هياكل البيانات هي صيغ متخصصة لتنظيم المعلومات وتخزينها ومعالجتها. تتضمن Python عدة هياكل بيانات مدمجة تسهّل إدارة مجموعات العناصر. سنستعرض في هذا الدرس هياكل البيانات الأربعة الرئيسية في Python: القوائم (lists)، والصفوف (tuples)، والقواميس (dictionaries)، والمجموعات (sets).

إن فهم هذه الهياكل ومعرفة متى تستخدم كل واحد منها أمر أساسي لكتابة شيفرة Python فعّالة وأنيقة.

القوائم

تُعدّ القوائم من أكثر هياكل البيانات تنوعًا واستخدامًا في Python. القائمة هي مجموعة مرتبة وقابلة للتعديل من العناصر.

إنشاء القوائم

# Liste vide
ma_liste = []

# Liste avec des éléments
nombres = [1, 2, 3, 4, 5]
fruits = ["pomme", "banane", "orange"]
mixte = [1, "hello", 3.14, True]  # Peut contenir différents types

# Création avec la fonction list()
caracteres = list("Python")  # ['P', 'y', 't', 'h', 'o', 'n']

الوصول إلى عناصر القائمة

تبدأ فهرسة عناصر القائمة من 0.

fruits = ["pomme", "banane", "orange", "fraise", "kiwi"]

# Accès par index positif (depuis le début)
premier_fruit = fruits[0]  # "pomme"
troisieme_fruit = fruits[2]  # "orange"

# Accès par index négatif (depuis la fin)
dernier_fruit = fruits[-1]  # "kiwi"
avant_dernier = fruits[-2]  # "fraise"

# Découpage (slicing)
deux_premiers = fruits[0:2]  # ["pomme", "banane"]
du_deuxieme_au_quatrieme = fruits[1:4]  # ["banane", "orange", "fraise"]
tous_sauf_premier = fruits[1:]  # ["banane", "orange", "fraise", "kiwi"]
trois_premiers = fruits[:3]  # ["pomme", "banane", "orange"]

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

fruits = ["pomme", "banane", "orange"]

# Modification d'un élément
fruits[1] = "poire"  # ["pomme", "poire", "orange"]

# Ajout d'éléments
fruits.append("fraise")  # Ajoute à la fin: ["pomme", "poire", "orange", "fraise"]
fruits.insert(1, "kiwi")  # Insère à l'index 1: ["pomme", "kiwi", "poire", "orange", "fraise"]
fruits.extend(["cerise", "raisin"])  # Ajoute plusieurs éléments: ["pomme", "kiwi", "poire", "orange", "fraise", "cerise", "raisin"]

# Suppression d'éléments
fruits.remove("poire")  # Supprime la première occurrence de "poire"
fruit_supprime = fruits.pop(2)  # Supprime et retourne l'élément à l'index 2
del fruits[0]  # Supprime l'élément à l'index 0
fruits.clear()  # Vide la liste complètement

العمليات الشائعة على القوائم

nombres = [3, 1, 4, 1, 5, 9, 2, 6]

# Longueur
longueur = len(nombres)  # 8

# Minimum et maximum
minimum = min(nombres)  # 1
maximum = max(nombres)  # 9

# Somme
total = sum(nombres)  # 31

# Tri
nombres.sort()  # Trie la liste en place: [1, 1, 2, 3, 4, 5, 6, 9]
nombres_decroissants = sorted(nombres, reverse=True)  # Retourne une nouvelle liste triée: [9, 6, 5, 4, 3, 2, 1, 1]

# Inversion
nombres.reverse()  # Inverse la liste en place

# Comptage
occurrences_de_1 = nombres.count(1)  # 2

# Recherche d'index
premier_index_de_1 = nombres.index(1)  # Index de la première occurrence de 1

الاستيعاب القائمي (List Comprehension)

الاستيعاب القائمي هو صيغة موجزة لإنشاء قوائم اعتمادًا على متسلسلات موجودة.

# Sans compréhension de liste
carres = []
for x in range(10):
    carres.append(x**2)

# Avec compréhension de liste
carres = [x**2 for x in range(10)]  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

# Avec condition
nombres_pairs = [x for x in range(20) if x % 2 == 0]  # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

# Compréhension de liste plus complexe
matrice = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
aplati = [nombre for ligne in matrice for nombre in ligne]  # [1, 2, 3, 4, 5, 6, 7, 8, 9]

حالات الاستخدام الشائعة للقوائم

القوائم مثالية عندما تحتاج إلى:

  • تخزين مجموعة من العناصر بترتيب محدد
  • تعديل المجموعة بشكل متكرر (إضافة العناصر أو حذفها)
  • الوصول إلى العناصر بحسب موضعها
  • تخزين العناصر المكررة

أمثلة على التطبيقات:

  • قائمة المهام
  • سجل الإجراءات
  • طوابير المعالجة
  • السلاسل الزمنية للبيانات

الصفوف (Tuples)

الصفوف مشابهة للقوائم، لكنها غير قابلة للتعديل (immutable)، أي لا يمكن تغييرها بعد إنشائها. تجعلها هذه الخاصية أكثر كفاءة من حيث الذاكرة والأداء.

إنشاء الصفوف

# Tuple vide
mon_tuple = ()

# Tuple avec un seul élément (nécessite une virgule)
singleton = (42,)

# Tuple avec plusieurs éléments
coordonnees = (10, 20)
personne = ("Alice", 30, "Ingénieure")

# Création sans parenthèses (packing)
autre_tuple = 1, 2, 3

# Création avec la fonction tuple()
caracteres = tuple("Python")  # ('P', 'y', 't', 'h', 'o', 'n')

الوصول إلى عناصر الصف

يعمل الوصول إلى عناصر الصف بالطريقة نفسها المتّبعة مع القوائم:

coordonnees = (10, 20, 30, 40, 50)

x = coordonnees[0]  # 10
y = coordonnees[1]  # 20
dernier = coordonnees[-1]  # 50
sous_tuple = coordonnees[1:4]  # (20, 30, 40)

فكّ حزم الصف (Unpacking)

من الميزات المفيدة بشكل خاص في الصفوف فكّ الحزم:

# Déballage basique
point = (10, 20)
x, y = point  # x = 10, y = 20

# Déballage avec * pour capturer plusieurs éléments
premier, *milieu, dernier = (1, 2, 3, 4, 5)
# premier = 1, milieu = [2, 3, 4], dernier = 5

# Échange de variables
a, b = 1, 2
a, b = b, a  # a = 2, b = 1

العمليات على الصفوف

coordonnees = (10, 20, 30)
plus_dimensions = coordonnees + (40, 50)  # Concaténation: (10, 20, 30, 40, 50)
repete = coordonnees * 2  # Répétition: (10, 20, 30, 10, 20, 30)

دوال الصفوف

بما أن الصفوف غير قابلة للتعديل، فإن دوالها أقل من دوال القوائم:

nombres = (3, 1, 4, 1, 5, 9, 2)

longueur = len(nombres)  # 7
occurrences_de_1 = nombres.count(1)  # 2
premier_index_de_1 = nombres.index(1)  # 1

حالات الاستخدام الشائعة للصفوف

يُفضَّل استخدام الصفوف عندما:

  • تكون لديك مجموعة من العناصر لن تتغير
  • تريد منع التعديل العرضي للبيانات
  • تحتاج إلى مفتاح قابل للتجزئة (hashable) للقواميس (فالقوائم لا يمكن أن تكون مفاتيح)
  • تُرجع عدة قيم من دالة

أمثلة على التطبيقات:

  • الإحداثيات (x, y, z)
  • سجلات قواعد البيانات
  • المفاتيح المركّبة
  • قيم RGB للألوان
  • معلمات الإعداد الثابتة

القواميس (Dictionaries)

القواميس هي مجموعات غير مرتبة من أزواج المفتاح والقيمة. وهي تتيح الوصول إلى العناصر وإدراجها وحذفها بسرعة عبر المفتاح.

إنشاء القواميس

# Dictionnaire vide
mon_dict = {}

# Dictionnaire avec des paires clé-valeur
etudiant = {
    "nom": "Martin",
    "age": 22,
    "cours": ["Mathématiques", "Informatique", "Physique"]
}

# Création avec la fonction dict()
coordonnees = dict(x=10, y=20, z=30)

# Création à partir de tuples clé-valeur
items = [("pomme", 3), ("banane", 5), ("orange", 2)]
inventaire = dict(items)

# Dictionnaire par compréhension
carre_des_nombres = {x: x**2 for x in range(6)}  # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

الوصول إلى القيم وتعديلها

etudiant = {
    "nom": "Martin",
    "age": 22,
    "cours": ["Mathématiques", "Informatique", "Physique"]
}

# Accès aux valeurs
nom = etudiant["nom"]  # "Martin"

# Modification des valeurs
etudiant["age"] = 23
etudiant["cours"].append("Chimie")

# Accès sécurisé avec get()
telephone = etudiant.get("telephone")  # None car la clé n'existe pas
telephone = etudiant.get("telephone", "Non spécifié")  # Valeur par défaut "Non spécifié"

# Ajout d'une nouvelle paire clé-valeur
etudiant["email"] = "martin@example.com"

# Suppression
cours = etudiant.pop("cours")  # Supprime et retourne la valeur
del etudiant["age"]  # Supprime la paire clé-valeur
etudiant.clear()  # Vide le dictionnaire

دوال القواميس

produits = {
    "pomme": 0.80,
    "banane": 0.50,
    "orange": 0.70
}

# Récupération des clés, valeurs et items
cles = produits.keys()  # dict_keys(['pomme', 'banane', 'orange'])
valeurs = produits.values()  # dict_values([0.8, 0.5, 0.7])
items = produits.items()  # dict_items([('pomme', 0.8), ('banane', 0.5), ('orange', 0.7)])

# Mise à jour du dictionnaire
nouveaux_produits = {"kiwi": 1.20, "banane": 0.55}
produits.update(nouveaux_produits)  # Ajoute "kiwi" et modifie le prix de "banane"

# Vérification de l'existence d'une clé
if "pomme" in produits:
    print("Le prix des pommes est", produits["pomme"])

التكرار على القواميس

produits = {
    "pomme": 0.80,
    "banane": 0.50,
    "orange": 0.70
}

# Itération sur les clés (comportement par défaut)
for produit in produits:
    print(produit)

# Itération sur les valeurs
for prix in produits.values():
    print(prix)

# Itération sur les paires clé-valeur
for produit, prix in produits.items():
    print(f"{produit}: {prix}€")

القواميس المتداخلة

# Dictionnaire de dictionnaires
etudiants = {
    "101": {
        "nom": "Alice",
        "age": 22,
        "cours": ["Math", "Informatique"]
    },
    "102": {
        "nom": "Bob",
        "age": 21,
        "cours": ["Physique", "Biologie"]
    }
}

# Accès aux éléments imbriqués
nom_etudiant_102 = etudiants["102"]["nom"]  # "Bob"
cours_alice = etudiants["101"]["cours"][1]  # "Informatique"

حالات الاستخدام الشائعة للقواميس

القواميس مثالية في الحالات التالية:

  • المجموعات التي تبحث فيها عن العناصر بمفتاح فريد
  • تخزين البيانات الترابطية (أزواج المفتاح والقيمة)
  • جداول التجزئة السريعة للبحث
  • تمثيل الكائنات بخصائصها

أمثلة على التطبيقات:

  • ذاكرة التخزين المؤقت للبيانات (cache)
  • حساب التكرارات
  • قواعد البيانات في الذاكرة
  • معلمات الإعداد
  • تخزين خصائص كائنات JSON

المجموعات (Sets)

المجموعات (sets) هي مجموعات غير مرتبة من العناصر الفريدة. وهي مهيأة لاختبار الانتماء وإزالة التكرارات.

إنشاء المجموعات

# Ensemble vide (ne peut pas utiliser {}, car cela crée un dictionnaire vide)
mon_ensemble = set()

# Ensemble avec des éléments
couleurs = {"rouge", "vert", "bleu"}

# Création à partir d'une liste (élimine les doublons)
nombres = set([1, 2, 2, 3, 4, 4, 5])  # {1, 2, 3, 4, 5}

# Ensemble par compréhension
nombres_pairs = {x for x in range(10) if x % 2 == 0}  # {0, 2, 4, 6, 8}

العمليات على المجموعات

fruits1 = {"pomme", "banane", "orange"}
fruits2 = {"orange", "kiwi", "ananas"}

# Ajout et suppression d'éléments
fruits1.add("fraise")
fruits1.remove("banane")  # Lève une erreur si l'élément n'existe pas
fruits1.discard("cerise")  # Ne lève pas d'erreur si l'élément n'existe pas
element = fruits1.pop()  # Supprime et retourne un élément arbitraire
fruits1.clear()  # Vide l'ensemble

# Vérification d'appartenance
"orange" in fruits2  # True
"banane" in fruits2  # False

العمليات المجموعاتية

تتيح المجموعات تنفيذ العمليات الرياضية على المجموعات:

A = {1, 2, 3, 4, 5}
B = {4, 5, 6, 7, 8}

# Union (éléments qui sont dans A OU dans B)
union = A | B  # {1, 2, 3, 4, 5, 6, 7, 8}
# ou
union = A.union(B)

# Intersection (éléments qui sont dans A ET dans B)
intersection = A & B  # {4, 5}
# ou
intersection = A.intersection(B)

# Différence (éléments qui sont dans A mais PAS dans B)
difference = A - B  # {1, 2, 3}
# ou
difference = A.difference(B)

# Différence symétrique (éléments qui sont dans A OU B mais PAS dans les deux)
diff_sym = A ^ B  # {1, 2, 3, 6, 7, 8}
# ou
diff_sym = A.symmetric_difference(B)

# Vérifier si un ensemble est un sous-ensemble d'un autre
est_sous_ensemble = {1, 2}.issubset(A)  # True

# Vérifier si un ensemble est un sur-ensemble d'un autre
est_sur_ensemble = A.issuperset({1, 2})  # True

المجموعات المجمّدة (frozenset)

الـ frozenset هو مجموعة غير قابلة للتعديل، مما يجعله قابلًا للتجزئة (hashable). ويمكن استخدامه مفتاحًا في القواميس.

# Création d'un frozenset
couleurs_primaires = frozenset(["rouge", "bleu", "jaune"])

# Utilisation comme clé de dictionnaire
groupes_couleurs = {
    frozenset(["rouge", "bleu", "jaune"]): "primaires",
    frozenset(["violet", "orange", "vert"]): "secondaires"
}

حالات الاستخدام الشائعة للمجموعات

المجموعات مفيدة بشكل خاص في الحالات التالية:

  • إزالة العناصر المكررة من مجموعة
  • اختبار انتماء العناصر بسرعة
  • تنفيذ العمليات الرياضية على المجموعات
  • إيجاد العناصر الفريدة أو المشتركة بين المجموعات

أمثلة على التطبيقات:

  • تصفية العناصر المكررة
  • تحليل البيانات الفريدة
  • العمليات على مجموعات الوسوم (tags)
  • إدارة صلاحيات المستخدمين
  • تمثيل الرسوم البيانية (نظرية المجموعات)

اختيار هيكل البيانات المناسب

لكل هيكل بيانات نقاط قوته وضعفه. إليك جدولًا مقارنًا يساعدك على اختيار الهيكل الأنسب لاحتياجك:

الهيكلمرتّبقابل للتعديلعناصر مفهرسةعنصر مفتاح-قيمةعناصر فريدةحالة الاستخدام النموذجية
قائمة✅✅✅❌❌مجموعة مرتبة وقابلة للتعديل
صف✅❌✅❌❌مجموعة مرتبة وغير قابلة للتعديل
قاموس❌¹✅❌✅✅ (المفاتيح)ربط المفاتيح بالقيم
مجموعة❌✅❌❌✅إزالة التكرارات والعمليات المجموعاتية

¹ منذ Python 3.7، تحتفظ القواميس بترتيب الإدراج، لكنها لا تُعدّ مرتبة بطبيعتها في تصميمها.

نصائح لاختيار الهيكل المناسب

  • استخدم القائمة عندما يكون الترتيب والتعديل مهمّين
  • استخدم الصف للبيانات للقراءة فقط أو للمفاتيح المركّبة
  • استخدم القاموس لعمليات البحث السريعة بالمفتاح
  • استخدم المجموعة عندما تكون الفرادة والعمليات المجموعاتية مطلوبة

مثال عملي: تحليل البيانات

إليك مثالًا يستخدم جميع هياكل البيانات لتحليل المبيعات:

# بيانات المبيعات (المنتج، الكمية، السعر، الفئة)
ventes = [
    ("pomme", 5, 0.80, "fruits"),
    ("banane", 3, 0.50, "fruits"),
    ("pain", 2, 1.20, "boulangerie"),
    ("lait", 1, 0.90, "laitier"),
    ("fromage", 2, 2.50, "laitier"),
    ("pomme", 2, 0.80, "fruits"),
    ("yaourt", 4, 0.60, "laitier")
]

# استخدام القواميس للتجميع حسب الفئة
ventes_par_categorie = {}
for produit, quantite, prix, categorie in ventes:
    if categorie not in ventes_par_categorie:
        ventes_par_categorie[categorie] = []
    ventes_par_categorie[categorie].append((produit, quantite, prix))

# استخدام المجموعات للحصول على منتجات فريدة
produits_uniques = {produit for produit, _, _, _ in ventes}
print(f"Produits uniques: {produits_uniques}")  # {'pain', 'pomme', 'fromage', 'lait', 'yaourt', 'banane'}

# استخدام الصفوف (tuples) لتخزين إجماليات كل فئة (غير قابلة للتعديل)
totaux_par_categorie = tuple(
    (categorie, sum(quantite * prix for _, quantite, prix in produits))
    for categorie, produits in ventes_par_categorie.items()
)
print("Totaux par catégorie:", totaux_par_categorie)

# استخدام القوائم والاشتمالات (comprehensions) لتحليل المبيعات
total_par_produit = {}
for produit, quantite, prix, _ in ventes:
    if produit in total_par_produit:
        total_par_produit[produit] = (total_par_produit[produit][0] + quantite, prix)
    else:
        total_par_produit[produit] = (quantite, prix)

# قائمة مرتبة للمنتجات حسب رقم المعاملات
ca_par_produit = [(produit, quantite * prix) for produit, (quantite, prix) in total_par_produit.items()]
ca_par_produit.sort(key=lambda x: x[1], reverse=True)

print("Produits par chiffre d'affaires:")
for produit, ca in ca_par_produit:
    print(f"- {produit}: {ca:.2f}€")

أداء هياكل البيانات

في التطبيقات التي تتعامل مع كميات كبيرة من البيانات، يصبح الأداء أمرًا مهمًا. فيما يلي نظرة عامة على التعقيد الزمني للعمليات الشائعة:

العمليةالقائمة (List)الصف (Tuple)القاموس (Dictionary)المجموعة (Set)
الوصول عبر الفهرسO(1)O(1)N/AN/A
الوصول عبر المفتاحN/AN/AO(1)¹N/A
البحث عن عنصرO(n)O(n)O(1)¹O(1)¹
إضافة عنصرO(1)²N/AO(1)¹O(1)¹
حذف عنصرO(n)N/AO(1)¹O(1)¹

¹ في المتوسط. وفي أسوأ الحالات (النادرة)، قد تصبح هذه العمليات O(n).
² الإضافة في النهاية هي O(1) بالتكلفة المطفأة (amortized). أما الإدراج في المنتصف فهو O(n).

خاتمة

تُعد هياكل البيانات اللبنات الأساسية لأي برنامج بلغة Python. إن فهم خصائصها ومزاياها وعيوبها سيساعدك على كتابة شيفرة أكثر كفاءة وأناقة.

للتلخيص:

  • القوائم متعددة الاستخدامات وقابلة للتعديل، وهي مثالية للمجموعات المرتبة
  • الصفوف (tuples) غير قابلة للتعديل وفعّالة، وهي مثالية للبيانات المخصصة للقراءة فقط
  • القواميس توفر بحثًا سريعًا عبر المفتاح، وهي مثالية للارتباطات
  • المجموعات (sets) تزيل التكرارات وتتيح عمليات مجموعاتية فعّالة

يُعد اختيار الهيكل المناسب لكل حالة مهارة تتحسن مع الممارسة. لا تتردد في تجربة أساليب مختلفة لحل مشكلات البيانات لديك.

في الدرس القادم، سنستكشف الدوال في Python وكيفية استخدامها لتنظيم شيفرتك وإعادة استخدامها بفعالية.


هل تحتاج إلى مراجعة أساسيات Python؟ اطلع على درسنا حول أساسيات صيغة Python.

التعليقات

التعليقات مدعومة عبر GitHub Discussions

سجّل الدخول باستخدام GitHub للمشاركة في النقاش

تم نسخ الرابط!