التكرار على القوائم المتداخلة
يمكنك استخدام حلقة متداخلة للمرور على كل عنصر وكل عنصر داخلي في قائمة متداخلة. انظر مثلًا إلى هذه القائمة:
numbers = [[1, 2, 3], [4, 5], [6], []]
انسخ القائمة إلى المحرر، ثم اكتب الحلقة المتداخلة التالية:
for sublist in numbers:
for num in sublist:
print(num)
print('---')
تأمل الكود جيدًا. الحلقة الخارجية تنشئ المتغير sublist، ثم الحلقة الداخلية تمر على العناصر الموجودة في المتغير نفسه. هذا نمط شائع جدًا. شغّل الكود الآن.
تتبّع تنفيذ الحلقة المتداخلة خطوة بخطوة. راقب كيف تتغير قيمة sublist مع كل دورة من الحلقة الخارجية، وكيف تمر الحلقة الداخلية على عناصر القائمة الفرعية الحالية قبل أن تنتقل الحلقة الخارجية إلى القائمة الفرعية التالية.
لنحل الآن بعض المسائل باستخدام هذا النوع من الحلقات.
لنفترض أن لدينا قائمة متداخلة من النصوص مثل الآتية، ونريد البحث عن كلمة محددة word في أعماق القائمة:
strings = [
[
"hello there",
"how are you",
],
[
"goodbye world",
"hello world",
]
]
word = "hello"
يمكنك تخيل أن strings تمثل كتابًا، وكل قائمة فرعية صفحة، وكل نص داخلها سطرًا في الصفحة. ويمكن أيضًا أن تمثل مكتبة، حيث كل قائمة كتاب وكل نص صفحة.
اكتب برنامجًا يطبع كل نص يحتوي على word. يجب أن يعمل لأي قيمتي word وstrings. في المثال السابق يجب أن يطبع:
hello there
hello world
تذكّر أن هناك طريقة محددة للتحقق مما إذا كان نص يحتوي على نص آخر.
كيف تتحقق أن نصًا يحتوي كلمة؟
تأكد أنك تفحص هل النص يحتوي الكلمة، لا القائمة الفرعية.
كيف تصل إلى كل نص داخل كل قائمة فرعية في قائمة متداخلة؟
تحتاج إلى حلقة متداخلة.
يجب أن تتبع الحلقات النمط نفسه الموجود في مثال بداية الصفحة.
جميل!
لنغيّر المسألة قليلًا. هذه المرة نريد أن يخبرنا الناتج أي القوائم الفرعية تحتوي على word، بدل طباعة النصوص الداخلية نفسها. اطبع قيمة منطقية لكل قائمة فرعية: True إذا كانت الكلمة موجودة في أي نص داخلها، وFalse إذا لم تظهر في أي نص.
مع المدخلات التالية:
strings = [
[
"hello there",
"how are you",
],
[
"goodbye world",
"hello world",
]
]
word = "goodbye"
يجب أن يطبع البرنامج:
False
True
لاحظ أن word in sublist لن يحل المسألة. مثلًا التعبير "hello" in ["hello there", "how are you"] يعطي False لأن "hello" ليست مساوية لأي عنصر كامل في القائمة، رغم أنها جزء من أحد النصوص.
لكل قائمة فرعية أنشئ متغيرًا منطقيًا.
مر على القائمة الفرعية وحدّث المتغير المنطقي حسب الحاجة.
اطبع المتغير المنطقي مرة واحدة فقط لكل قائمة فرعية.
ما القيمة الابتدائية المناسبة للمتغير المنطقي؟
ماذا لو كانت إحدى القوائم الفرعية فارغة؟ ماذا يجب أن تطبع لها؟
إذا وجدت الكلمة في نص، اجعل المتغير المنطقي
True.وماذا إذا لم يحتوِ أحد النصوص على الكلمة؟
لا يهم؛ هذا لا يغيّر احتمال أن يحتوي نص آخر على الكلمة.
بعبارة أخرى، لا تضبط المتغير إلى
Falseإلا في البداية.
أحسنت!
الآن اطبع قيمة منطقية واحدة فقط تخبرنا هل word موجودة في أي نص في القائمة المتداخلة كلها. مثلًا إذا كانت القيم:
strings = [
[
"hello there",
"how are you",
],
[
"goodbye world",
"hello world",
]
]
word = "Python"
فيجب أن يطبع البرنامج False.
هذا يشبه التمرين السابق جدًا.
متى يجب أن تطبع المتغير المنطقي؟
تذكر أنك تريد طباعته مرة واحدة فقط.
بدل إنشاء متغير منطقي لكل قائمة فرعية، أنشئ متغيرًا واحدًا للقائمة كلها.
متى وكيف يجب تعديل هذا المتغير؟
في جزء سابق من الدورة كان هناك تمرين لطباعة نصين رأسيًا جنبًا إلى جنب، مثل:
H W
e o
l r
l l
o d
الآن سنعمم الفكرة على قائمة من النصوص بدل نصين فقط.
في هذا التمرين تحصل على قائمة من النصوص متساوية الطول. اكتب برنامجًا يطبع الحرف الأول من كل نص في سطر واحد، ثم الحرف الثاني من كل نص في السطر التالي، وهكذا. مثلًا إذا كانت:
strings = ["abc", "def", "ghi"]
فيجب أن يطبع:
adg
beh
cfi
يجب أن يعمل البرنامج لأي قائمة تحقق هذا الشرط. وإذا استخدمت القائمة التالية فستكتشف رسالة مخفية من Zen of Python:
strings = [" b n", "f ete", "liths", "astat", "t ene", " r d"]
هذه المرة لا تضف مسافات بين الحروف في الناتج.
هذا لا يشبه التمارين السابقة في هذه الصفحة.
فكر في حل المسألة عندما يوجد نصان فقط. كيف تعممه على قائمة من النصوص؟
ستحتاج إلى المرور على المحارف الأولى، ثم الثانية، وهكذا.
ستستخدم حلقة، لكن كم دورة يجب أن تنفذ؟
تذكر أن النصوص في القائمة متساوية في الطول.
لكل موضع، الأول ثم الثاني وهكذا، أنشئ نصًا جديدًا.
ما القيمة الابتدائية لهذا النص؟
لكل موضع ستحتاج إلى المرور على كل نص في القائمة.
ستحتاج إلى حلقة أخرى داخل الحلقة الحالية.
أحسنت! يمكنك الانتقال إلى الصفحة التالية الآن، أو حل تحدٍّ إضافي.
لنطوّر التمرين السابق بحيث يعمل حتى عندما تكون النصوص داخل القائمة مختلفة الأطوال.
مرّ على المواضع من الأول حتى طول أطول نص. في كل موضع، أضف حرف النص إذا كان ذلك النص يحتوي على حرف في هذا الموضع، وإلا أضف مسافة. ثم اطبع السطر الناتج. بهذه الطريقة تحافظ على محاذاة النصوص حتى عندما ينتهي بعضها قبل الآخر.
بما أن النصوص قد تختلف في الطول، فالأمر أصعب قليلًا.
إلى أي حد يجب أن تستمر الحلقة الخارجية هذه المرة؟
قبل التعامل مع النصوص، من المفيد أن تجد طول أطول نص أولًا.
الباقي يشبه التمرين السابق جدًا.
الفرق الوحيد أنك الآن تحتاج إلى تحديد هل تضيف محرفًا من النص أم مسافة.
أتقنت القوائم المتداخلة وكيفية دمجها مع الحلقات المتداخلة. لديك الآن أدوات قوية جدًا لبناء برامج أكثر تعقيدًا.