كيفية التكرار عبر القاموس في بايثون

يوفر بايثون عدة طرق لتكرار عملية البحث في القاموس، مثل استخدام .items() للوصول مباشرةً إلى أزواج المفتاح-القيمة، و.values() لاسترجاع القيم فقط. بفهم هذه التقنيات، ستتمكن من الوصول إلى بيانات القاموس ومعالجتها بكفاءة.

للاستفادة القصوى من هذا الدرس، يجب أن يكون لديك فهم أساسي لقواميس بايثون، ومعرفة كيفية استخدام حلقات بايثون (for loops). كما أن معرفة أدوات أخرى، مثل الدالتين المدمجتين map() وfilter()، بالإضافة إلى وحدتي itertools وcollections، تُعدّ ميزة إضافية.

البدء باستخدام قواميس بايثون

تُعدّ القواميس حجر الزاوية في بايثون. فالعديد من جوانب اللغة مبنية على القواميس. الوحدات النمطية، والفئات، والكائنات، و ()globals، و ()locals كلها أمثلة على كيفية ترابط القواميس بشكل وثيق في تطبيق بايثون.

فيما يلي كيفية تعريف القاموس في وثائق Python الرسمية:

مصفوفة ترابطية، حيث تُربط مفاتيح عشوائية بقيم. يمكن أن تكون المفاتيح أي كائن باستخدام دالتَيْ __hash__() و  __eq__(). (المصدر)

هناك عدة نقاط يجب ملاحظتها في هذا التعريف:

  • تربط القواميس المفاتيح بالقيم، وتخزنها في مصفوفة أو مجموعة. تُعرف أزواج المفتاح-القيمة عادةً بالعناصر.
  • يجب أن تكون مفاتيح القاموس من نوع قابل للتجزئة، مما يعني أنه يجب أن يكون لها قيمة تجزئة لا تتغير أبدًا أثناء عمر المفتاح.

بخلاف التسلسلات، وهي عناصر قابلة للتكرار تدعم الوصول إلى العناصر باستخدام مؤشرات عددية صحيحة، تُفهرس القواميس باستخدام المفاتيح. هذا يعني أنه يمكنك الوصول إلى القيم المخزنة في القاموس باستخدام المفتاح المرتبط به بدلاً من مؤشر عددي صحيح.

المفاتيح في القاموس تشبه إلى حد كبير المجموعة، وهي عبارة عن مجموعة من الكائنات الفريدة والقابلة للتجزئة. ولأن المفاتيح يجب أن تكون قابلة للتجزئة، فلا يمكنك استخدام الكائنات القابلة للتغيير كمفاتيح قاموس.

من ناحية أخرى، يمكن أن تكون قيم القاموس من أي نوع في بايثون، سواءً كانت قابلة للتجزئة أم لا. لا توجد قيود على القيم. يمكنك استخدام أي شيء كقيمة في قاموس بايثون.

ملاحظة: المفاهيم والمواضيع التي ستتعلمها في هذا القسم وخلال هذا الدرس تتعلق بتطبيق CPython للغة بايثون. قد تُظهر تطبيقات أخرى، مثل PyPy وIronPython وJython، سلوكيات وميزات قاموسية مختلفة تتجاوز نطاق هذا الدرس.

قبل إصدار بايثون 3.6، كانت القواميس هياكل بيانات غير مرتبة. هذا يعني أن ترتيب العناصر عادةً لا يتطابق مع ترتيب الإدراج:

>>> # Python 3.5
>>> likes = {"color": "blue", "fruit": "apple", "pet": "dog"}

>>> likes
{'color': 'blue', 'pet': 'dog', 'fruit': 'apple'}

لاحظ كيف أن ترتيب العناصر في القاموس الناتج لا يتطابق مع الترتيب الذي أدخلت العناصر به في الأصل.

في بايثون 3.6 وما بعده، تحتفظ مفاتيح وقيم القاموس بنفس الترتيب الذي تُدخلها به في القاموس الأساسي. بدءًا من 3.6، أصبحت القواميس هياكل بيانات مُرتبة ومُدمجة.

>>> # Python 3.6
>>> likes = {"color": "blue", "fruit": "apple", "pet": "dog"}

>>> likes
{'color': 'blue', 'fruit': 'apple', 'pet': 'dog'}

يُعدّ ترتيب العناصر ميزةً مفيدةً للغاية. مع ذلك، إذا كنت تعمل على كود يدعم إصدارات بايثون القديمة، فلا يجب عليك الاعتماد على هذه الميزة، لأنها قد تُسبب أخطاءً برمجية. أما مع الإصدارات الأحدث، فمن الآمن تمامًا الاعتماد عليها.

من الميزات المهمة الأخرى للقواميس أنها أنواع بيانات قابلة للتغيير. هذا يعني أنه يمكنك إضافة عناصرها وحذفها وتحديثها حسب الحاجة. تجدر الإشارة إلى أن هذه القابلية للتغيير تعني أيضًا عدم إمكانية استخدام قاموس كمفتاح في قاموس آخر.

فهم كيفية التكرار عبر القاموس في بايثون

بصفتك مطور بايثون، ستجد نفسك غالبًا في مواقف تتطلب منك تكرار قاموس موجود أثناء تنفيذ بعض الإجراءات على أزواج المفتاح والقيمة فيه. لذلك، من المهم أن تتعرف على الخيارات المختلفة لتكرار القاموس في بايثون.

عند استخدام بايثون لتكرار القواميس، تُقدم هذه اللغة أدوات وتقنيات رائعة لمساعدتك. ستتعلم في هذا الدرس العديد من هذه الأدوات والتقنيات. في البداية، ستتعلم أساسيات تكرار القواميس ومفاتيحها وقيمها وعناصرها باستخدام حلقات for.

التنقل عبر القاموس مباشرةً

تحتوي قواميس بايثون على دوال خاصة يستخدمها بايثون داخليًا لإجراء بعض العمليات. تعتمد هذه الدوال على قاعدة التسمية بإضافة شرطة سفلية مزدوجة في بداية ونهاية اسم الدالة.

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

>>> dir({})
['__class__', '__contains__', '__delattr__', ... , '__iter__', ...]

عند التدقيق في المخرجات السابقة، نجد المدخل ‘__iter__‘، وهو دالة يستدعيها بايثون تلقائيًا عند الحاجة إلى مُكرر لنوع بيانات الحاوية. يجب أن تُعيد هذه الدالة كائن مُكرر جديد، مما يسمح لك بتكرار جميع عناصر نوع الحاوية الأساسي.

بالنسبة لقواميس بايثون، تسمح دالة .__iter__() بالتكرار المباشر على المفاتيح افتراضيًا. هذا يعني أنه إذا استخدمت قاموسًا مباشرةً في حلقة for، فسيستدعي بايثون تلقائيًا دالة .__iter__ على هذا القاموس، وستحصل على مُكرر يكرر مفاتيحه:

>>> likes = {"color": "blue", "fruit": "apple", "pet": "dog"}

>>> for key in likes:
...     print(key)
...
color
fruit
pet

بايثون ذكي بما يكفي ليعرف أن likes عبارة عن قاموس، وأنه ينفذ دالة .__iter__(). في هذا المثال، يستدعي بايثون دالة .__iter__() تلقائيًا، مما يسمح لك بتكرار مفاتيح likes دون بذل أي جهد إضافي.

هذه هي الطريقة الأساسية لتكرار القاموس في بايثون. ما عليك سوى وضع القاموس مباشرةً في حلقة for، وستكون قد انتهيت!

إذا استخدمت هذا النهج مع عامل [المفتاح]، فيمكنك الوصول إلى قيم القاموس الخاص بك أثناء التنقل عبر المفاتيح:

>>> for key in likes:
...     print(key, "->", likes[key])
...
color -> blue
fruit -> apple
pet -> dog

في هذا المثال، تستخدم key وlikes[key] في الوقت نفسه للوصول إلى مفاتيح وقيم قاموسك المستهدف، على التوالي. تتيح لك هذه التقنية إجراء عمليات مختلفة على كلٍّ من مفاتيح وقيم likes.

على الرغم من أن تكرار القاموس مباشرةً في بايثون أمرٌ سهلٌ للغاية، إلا أنك ستجد غالبًا أن القواميس توفر أدواتٍ أكثر سهولةً ووضوحًا لتحقيق النتيجة نفسها. هذا هو الحال مع دالة ()items، التي تُعرّف طريقةً سريعةً لتكرار العناصر أو أزواج المفاتيح والقيم في القاموس.

التكرار على عناصر القاموس: تابع .items()

عند العمل مع القواميس، قد يكون تكرار كلٍّ من المفاتيح والقيم في آنٍ واحد متطلبًا شائعًا. تتيح لك دالة .items() القيام بذلك تمامًا. تُرجع هذه الدالة كائن عرض يحتوي على عناصر القاموس كمجموعات مفتاح-قيمة:

>>> likes = {"color": "blue", "fruit": "apple", "pet": "dog"}

>>> likes.items()
dict_items([('color', 'blue'), ('fruit', 'apple'), ('pet', 'dog')])

توفر عناصر عرض القاموس عرضًا ديناميكيًا لعناصر القاموس. الديناميكية هنا تعني أنه عند تغير القاموس، تعكس العروض هذه التغييرات.

تعتبر العروض قابلة للتكرار، لذا يمكنك التكرار خلال عناصر القاموس باستخدام كائن العرض الناتج عن استدعاء .items()، كما يمكنك أن ترى في المثال أدناه:

>>> for item in likes.items():
...     print(item)
...
('color', 'blue')
('fruit', 'apple')
('pet', 'dog')

في هذا المثال، تقوم .items() بإرجاع كائن عرض ينتج أزواجًا من القيمة الرئيسية واحدة تلو الأخرى ويسمح لك بالتكرار من خلالها.

إذا ألقيت نظرة فاحصة على العناصر الفردية التي ينتجها .items()، فستلاحظ أنها عبارة عن كائنات ثلاثية:

>>> for item in likes.items():
...     print(item)
...     print(type(item))
...
('color', 'blue')
<class 'tuple'>
('fruit', 'apple')
<class 'tuple'>
('pet', 'dog')
<class 'tuple'>

في هذه الحلقة المُحدّثة، تستخدم الدالة المُدمجة ()type للتحقق من نوع بيانات كل عنصر ينتجه .items(). وكما هو واضح في مُخرَج الحلقة، جميع العناصر هي مجموعات. بعد معرفة ذلك، يمكنك استخدام فك حزم المجموعات لتكرار المفاتيح والقيم بالتوازي.

لتحقيق التكرار المتوازي من خلال المفاتيح والقيم، كل ما عليك فعله هو فك ضغط عناصر كل عنصر إلى متغيرين مختلفين، أحدهما للمفتاح والآخر للقيمة:

>>> for key, value in likes.items():
...     print(key, "->", value)
...
color -> blue
fruit -> apple
pet -> dog

يقوم متغيرا المفتاح والقيمة في رأس حلقة for بعملية فك الضغط. في كل مرة تُشغّل فيها الحلقة، يحصل المفتاح على مرجع للمفتاح الحالي، ويحصل القيمة على مرجع للقيمة. بهذه الطريقة، يمكنك التحكم بشكل أكبر في محتوى القاموس. وبالتالي، ستتمكن من معالجة المفاتيح والقيم بشكل منفصل بطريقة سهلة القراءة وبلغة Python.

التكرار عبر مفاتيح القاموس: تابع .keys()

تُتيح قواميس بايثون تابع أخر لتكرار مفاتيحها. فبالإضافة إلى استخدام القاموس المستهدف مباشرةً في حلقة، يُمكنك أيضًا استخدام دالة .keys() . تُرجع هذه الدالة كائن عرض يحتوي فقط على مفاتيح القاموس:

>>> likes = {"color": "blue", "fruit": "apple", "pet": "dog"}

>>> likes.keys()
dict_keys(['color', 'fruit', 'pet'])

تُرجع دالة .keys() كائنًا يُوفر عرضًا ديناميكيًا للمفاتيح في قائمة  likes. يمكنك استخدام هذا الكائن لعرض مفاتيح القاموس. للقيام بذلك، استدعِ دالة .keys() في رأس حلقة for:

>>> for key in likes.keys():
...     print(key)
...
color
fruit
pet

عند استدعاء دالة .keys() على  likes، ستحصل على عرض للمفاتيح. يعلم بايثون أن كائنات العرض قابلة للتكرار، لذا يبدأ في التكرار.

قد تتساءل عن سبب استخدام .keys() بدلاً من مجرد تكرار القاموس مباشرةً. الإجابة السريعة هي أن استخدام .keys() صراحةً يُتيح لك إيصال هدف التكرار على المفاتيح فقط بشكل أفضل.

التنقل عبر قيم القاموس: تابع .values()

من الاحتياجات الشائعة الأخرى التي ستواجهها عند تكرار القواميس هي تكرار القيم فقط. ولفعل ذلك، استخدم دالة .values()، التي تُرجع عرضًا يحتوي على القيم الموجودة في القاموس الأساسي:

>>> likes = {"color": "blue", "fruit": "apple", "pet": "dog"}

>>> likes.values()
dict_values(['blue', 'apple', 'dog'])

في هذا الكود، تُرجع دالة .values() كائن عرض يُنتج قيمًا من  likes. وكما هو الحال مع كائنات العرض الأخرى، فإن نتيجة دالة .values() قابلة للتكرار أيضًا، لذا يُمكنك استخدامها في حلقة تكرارية:

>>> for value in likes.values():
...     print(value)
...
blue
apple
dog

باستخدام دالة .values()، يمكنك الوصول فقط إلى قيم قاموسك المستهدف، مثلًا. يُرجى ملاحظة أن أداة التكرار هذه لا تتيح لك الوصول إلى المفتاح المرتبط بكل قيمة. لذا، يُنصح باستخدام هذه التقنية إذا كنت تحتاج فقط إلى الوصول إلى قيم قاموسك المستهدف.

تغيير قيم القاموس أثناء التكرار

قد تحتاج أحيانًا إلى تغيير قيم القاموس أثناء تكرارها في بايثون. في المثال التالي، يمكنك تحديث سعر مجموعة من المنتجات في القاموس:

>>> fruits = {"apple": 0.40, "orange": 0.35, "banana": 0.25}

>>> for fruit, price in fruits.items():
...     fruits[fruit] = round(price * 0.9, 2)
...

>>> fruits
{'apple': 0.36, 'orange': 0.32, 'banana': 0.23}

في هذا المثال، يمكنك استخدام التعبير fruit[fruit] = round(price * 0.9, 2) لتعديل قيم  fruits وتطبيق خصم بنسبة 10 بالمائة.

ملاحظة دقيقة في المثال أعلاه هي أنه لتحديث القيم، يجب استخدام القاموس الأصلي بدلاً من تحديث price الحالي مباشرةً باستخدام قيمة مثل price = round(price * 0.9, 2). لماذا تحتاج إلى fruit[fruit] إذا كان لديك وصول مباشر إلى price؟ هل من الممكن تحديث price مباشرةً؟

المشكلة الحقيقية هي أن إعادة تعيين fruit أو  price لا ينعكس في القاموس الأصلي. ما يحدث في الواقع هو أنك ستفقد الإشارة إلى مكون القاموس دون تغيير أي شيء فيه.

إزالة العناصر بأمان من القاموس أثناء التكرار

لأن قواميس بايثون قابلة للتغيير، يمكنك إزالة أزواج المفتاح والقيمة الموجودة منها حسب الحاجة. في المثال التالي، ستحذف عنصرًا بشكل انتقائي، وفقًا لقيمته المحددة. لاحظ أنه لتقليص حجم القاموس بأمان أثناء التكرار، يجب استخدام نسخة منه:

>>> fruits = {"apple": 0.40, "orange": 0.35, "banana": 0.25}

>>> for fruit in fruits.copy():
...     if fruits[fruit] >= 0.30:
...         del fruits[fruit]
...

>>> fruits
{'banana': 0.25}

في هذا المثال، تستخدم دالة .copy() لإنشاء نسخة سطحية من قاموسك المستهدف، Fruits. ثم تُكرر عملية النسخ أثناء إزالة عناصر من القاموس الأصلي. في هذا المثال، تستخدم عبارة del لإزالة عناصر القاموس. مع ذلك، يمكنك أيضًا استخدام دالة .pop() مع مفتاح الهدف كمُعامل.

إذا لم تستخدم نسخة من القاموس المستهدف أثناء محاولة إزالة العناصر في حلقة، فستحصل على خطأ:

>>> fruits = {"apple": 0.40, "orange": 0.35, "banana": 0.25}

>>> for fruit in fruits:
...     if fruits[fruit] >= 0.30:
...         del fruits[fruit]
...
Traceback (most recent call last):
  File "<input>", line 1, in <module>
    for fruit in fruits:
RuntimeError: dictionary changed size during iteration

عند محاولة إزالة عنصر من قاموس أثناء التكرار، يُطلق بايثون خطأً وقت التشغيل. ولأن حجم القاموس الأصلي قد تغير، فمن غير الواضح كيفية متابعة التكرار. لذا، لتجنب هذه المشكلة، استخدم دائمًا نسخة من قاموسك أثناء التكرار.

التكرار عبر القواميس: أمثلة على حلقة for

حتى الآن، تعلمتَ الطرق الأساسية لتكرار القاموس في بايثون. أنت الآن تعرف كيفية تكرار مفاتيح وقيم وعناصر القاموس باستخدام أدوات وتقنيات مختلفة. حان الوقت الآن للمضي قدمًا وكتابة بعض الأمثلة لما يمكنك فعله بمحتوى القاموس أثناء تكراره في حلقة for.

للبدء، ستبدأ بمثال حول كيفية تصفية عناصر القاموس حسب القيمة باستخدام حلقة for.

تصفية العناصر حسب قيمتها

أحيانًا، قد تجد نفسك في مواقف يكون لديك فيها قاموس وترغب في إنشاء قاموس جديد يحتوي فقط على البيانات التي تُلبي شرطًا مُحددًا. يمكنك القيام بذلك باستخدام جملة شرطية أثناء تصفحك للقاموس. خذ بعين الاعتبار المثال البسيط التالي:

>>> numbers = {"one": 1, "two": 2, "three": 3, "four": 4}

>>> small_numbers = {}

>>> for key, value in numbers.items():
...     if value <= 2:
...         small_numbers[key] = value
...

>>> small_numbers
{'one': 1, 'two': 2}

في هذا المثال، يمكنك تصفية العناصر بقيمة أقل من 2 وإضافتها إلى قاموس الأرقام الصغيرة. يحتوي هذا القاموس الجديد فقط على العناصر التي تُلبي شرط  value <= 2 وهو شرط التصفية.

هناك تقنية أخرى يمكنك استخدامها لتصفية العناصر من القاموس. كائنات عرض المفاتيح تشبه مجموعات بايثون، لذا فهي تدعم عمليات المجموعات، مثل الاتحاد والتقاطع والفرق. يمكنك الاستفادة من هذا السلوك الشبيه بسلوك المجموعات لتصفية مفاتيح معينة من القاموس.

على سبيل المثال، في الكود أدناه، يمكنك استخدام مجموعة الاختلافات لتصفية الحمضيات من قاموس fruits:

>>> fruits = {"apple": 0.40, "orange": 0.35, "banana": 0.25}

>>> fruits.keys() - {"orange"}
{'apple', 'banana'}

عند تشغيل الدالة fruit.keys() - {"orange"}، فأنت تُشغّل في الواقع عملية فرق بين المجموعات. يمكنك استخدام هذه الحيلة لإنشاء قاموس جديد بدون الحمضيات:

>>> non_citrus = {}

>>> for key in fruits.keys() - {"orange"}:
...     non_citrus[key] = fruits[key]
...

>>> non_citrus
{'apple': 0.4, 'banana': 0.25}

في هذا المثال، يمكنك إنشاء قاموس جديد من مجموعة المفاتيح التي تحصل عليها من حساب الفرق بين مفاتيح قاموسك ومجموعة من المفاتيح غير المرغوب فيها.

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

إجراء العمليات الحسابية باستخدام المفاتيح والقيم

إجراء حسابات باستخدام قيم القاموس أثناء تصفح القاموس نفسه مهمة شائعة أخرى. لنفترض أنك خزّنت بيانات مبيعات شركتك في قاموس، وتريد الآن معرفة إجمالي دخل السنة.

لحل هذه المشكلة، يمكنك استخدام متغير تراكمي بقيمة ابتدائية صفر. بعد ذلك، يمكنك تجميع كل قيمة موجودة في قاموسك في هذا المتغير:

>>> incomes = {"apple": 5600.00, "orange": 3500.00, "banana": 5000.00}
>>> total_income = 0.00

>>> for income in incomes.values():
...     total_income += income
...

>>> total_income
14100.0

هنا، تُكرر القيم في قاموس دخلك وتُجمعها تسلسليًا في إجمالي الدخل. يُؤدي التعيين المُعزَّز  total_income += income الغرض المطلوب، وفي نهاية الحلقة، تحصل على إجمالي الدخل للسنة.

كما هو الحال مع العديد من مهام بايثون، ستجد طريقة أفضل لإجراء نفس العمليات الحسابية، كما في المثال أدناه. يمكنك استخدام دالة ()sum المدمجة:

>>> sum(incomes.values())
14100.0

في هذا المثال، تُمرّر القيم من قاموس  incomes مباشرةً كوسيطة إلى دالة ()sum. تُكرّر الدالة ضمنيًا القيم وتحسب مجموعها في هذه العملية.

على الرغم من أن حل ()sum موجز وسريع وسهل القراءة، فإن حل الحلقة أكثر عمومية ويسمح لك بإجراء عمليات حسابية أخرى غير مجرد جمع القيم.

تبديل المفاتيح والقيم من خلال التكرار

لنفترض أن لديك قاموسًا وتحتاج إلى تحويل المفاتيح إلى قيم والقيم إلى مفاتيح. في هذه الحالة، يمكنك استخدام حلقة for للتكرار في القاموس الأصلي أثناء بناء القاموس الجديد باستخدام مفاتيح وقيم مُبدّلة:

>>> numbers = {"one": 1, "two": 2, "three": 3, "four": 4}
>>> swapped = {}

>>> for key, value in numbers.items():
...     swapped[value] = key
...

>>> swapped
{1: 'one', 2: 'two', 3: 'three', 4: 'four'}

التعبير swapped[value] = key يُنجز المهمة نيابةً عنك بتبديل المفاتيح والقيم في قاموس جديد. لاحظ أنه لكي يعمل هذا الكود، يجب أن تكون البيانات المخزنة في قيم قاموسك الأصلي من نوع بيانات قابل للتجزئة. وإلا، فسيظهر خطأ.

مرة أخرى، يوفر بايثون أدوات أخرى تتيح لك كتابة المثال السابق بإيجاز. هذه المرة، يمكنك استخدام دالة ()zip المدمجة مع دالة ()dict المُنشئة:

>>> dict(zip(numbers.values(), numbers.keys()))
{1: 'one', 2: 'two', 3: 'three', 4: 'four'}

في هذا المثال، تستخدم دالة ()zip لإنشاء أزواج من القيم والمفتاح. للقيام بذلك، تُكرر دالة ()zip ضمنيًا قيم ومفاتيح قاموس الأرقام. ثم تستخدم الأزواج الناتجة كوسائط لدالة ()dict لإنشاء القاموس المطلوب.

التنقل عبر القاموس بالترتيب المرتب والعكسي

قد تحتاج أحيانًا إلى تكرار القاموس بترتيب مُرتب. يمكنك القيام بذلك باستخدام الدالة المُدمجة ()sorted. عند استدعاء هذه الدالة مع عنصر قابل للتكرار كمُعامل، ستحصل على قائمة بالعناصر مُرتبة.

يُمكن أن يكون تكرار القاموس بترتيب عكسي متطلبًا شائعًا في الشيفرة البرمجية. في هذه الحالة، يُمكنك استخدام الدالة المُدمجة ()reversed، والتي تأخذ عنصرًا قابلًا للتكرار كمُعامل وتُنتج عناصره بترتيب عكسي.

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

التكرار على المفاتيح المصنفة

إذا كنت بحاجة إلى تكرار مفاتيح قاموس بترتيب مُرتب، فيمكنك تمرير قاموسك كمُعامل إلى الدالة ()sorted. ستحصل على قائمة تحتوي على المفاتيح بترتيب مُرتب. ستُتيح لك هذه القائمة التنقل عبر قاموسك مُرتبًا حسب المفاتيح:

>>> incomes = {"apple": 5600.00, "orange": 3500.00, "banana": 5000.00}

>>> for fruit in sorted(incomes):
...     print(fruit, "->", incomes[fruit])
...
apple -> 5600.0
banana -> 5000.0
orange -> 3500.0

في هذا المثال، يمكنك فرز المفاتيح باستدعاء دالة () sorted مع استخدام قاموسك كمُعامل. لاحظ أنه كان بإمكانك أيضًا استخدام دالة sorted(incomes.keys()) للحصول على نفس النتيجة. في كلتا الحالتين، ستحصل على قائمة تحتوي على مفاتيح قاموسك مرتبةً.

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

التكرار عبر القيم المصنفة

قد تحتاج أيضًا إلى تكرار قاموس بايثون مع فرز عناصره حسب القيم. للقيام بذلك، يمكنك استخدام الدالة ()sorted أيضًا. هذه المرة، ستحتاج إلى استخدام وسيطة ثانية تُسمى key عند استدعاء الدالة ()sorted. تُحدد هذه الوسيطة، التي تعتمد على الكلمات المفتاحية فقط، دالة ذات وسيطة واحدة لاستخراج مفتاح مقارنة من العناصر التي تُعالجها.

لتكرار عناصر القاموس المُرتبة حسب القيمة، يمكنك كتابة دالة تُرجع قيمة كل عنصر، ثم استخدام هذه الدالة كوسيطة رئيسية للدالة ()sorted. في المثال التالي، يمكنك القيام بذلك باستخدام دالة lambda قصيرة:

>>> incomes = {"apple": 5600.00, "orange": 3500.00, "banana": 5000.00}

>>> for fruit, income in sorted(incomes.items(), key=lambda item: item[1]):
...     print(fruit, "->", income)
...
orange -> 3500.0
banana -> 5000.0
apple -> 5600.0

في هذا المثال، تُعرّف دالة lambda وتستخدمها لفرز عناصر incomes حسب القيمة باستخدام الدالة ()sorted. تُوجّه دالة  lambda الدالة ()sorted لفرز عناصر الدخل حسب العنصر الثاني من كل عنصر، item[1]، وهو قيمة الدخل.

قد ترغب أيضًا في تكرار قيم القاموس بترتيب مُرتب دون مراعاة المفاتيح. في هذه الحالة، يمكنك استخدام .values() لتوفير الزيادة لـ ()sorted. إليك مثال سريع:

>>> for income in sorted(incomes.values()):
...     print(income)
...
3500.0
5000.0
5600.0

يؤدي استدعاء الدالة ()sorted مع incomes.values() كمُعامل إلى إرجاع قيم قاموسك مُرتبةً. تذكّر أن المفاتيح لن تكون متاحةً إذا استخدمتَ .values(). لا بأس. أحيانًا، لا تحتاج إلى المفاتيح، فقط القيم، وهذه طريقة سريعة للوصول إليها.

التكرار من خلال قاموس بترتيب عكسي

إذا كنت بحاجة إلى اجتياز قواميسك بترتيب عكسي فيمكنك استخدام الوسيطة العكسية ()sorted. هذه الحجة تأخذ قيمة منطقية. إذا كنت تستخدمTrue ، فسيتم فرز العناصر بترتيب عكسي:

>>> incomes = {"apple": 5600.00, "orange": 3500.00, "banana": 5000.00}

>>> for fruit in sorted(incomes, reverse=True):
...     print(fruit, "->", incomes[fruit])
...
orange -> 3500.0
banana -> 5000.0
apple -> 5600.0

في هذا المثال، ستُكرر مفاتيح  incomes بترتيب عكسي باستخدام الوسيطة العكسية لدالة ()sorted في رأس حلقة for. هذا المثال يُرتب المفاتيح. لماذا لا تُجرب كتابة مثال يُرتب القيم بترتيب عكسي؟

التنقل عبر القاموس بالترتيب العكسي

من الإمكانيات الأخرى التي يوفرها بايثون للتكرار عبر القواميس استخدام الدالة المضمنة ()reversed. تأخذ هذه الدالة عنصرًا قابلًا للتكرار كمعامل، ثم تُرجع مُكررًا يُنتج عناصر بترتيب عكسي.

باستخدام ()reversed، يمكنك التنقل بين قواميسك بالترتيب العكسي:

>>> numbers = {"one": 1, "two": 2, "three": 3, "four": 4}

>>> for key, value in reversed(numbers.items()):
...     print(key, "->", value)
...
four -> 4
three -> 3
two -> 2
one -> 1

التنقل بين قواميس متعددة كقواميس واحدة

توفر   وحدات collections و itertools من مكتبة Python القياسية مجموعة من الأدوات المفيدة التي تسمح لك بالتكرار عبر قواميس متعددة دفعة واحدة.

في collections، ستجد فئة ChainMap، التي تتيح لك إنشاء كائن يشبه القاموس من خلال دمج قواميس متعددة موجودة. باستخدام ChainMap، يمكنك التنقل بين عدة قواميس كما لو كانت قواميس واحدة.

ستجد في itertools دالة تسمى ()chain والتي تسمح لك بالتكرار عبر قواميس Python متعددة واحدة تلو الأخرى.

في الأقسام التالية، ستتعلم كيفية استخدام هاتين الأداتين لتكرار عدة قواميس في دورة واحدة. ستتعلم أيضًا كيف تختلف الأداتان عن بعضهما البعض.

التكرار عبر قواميس متعددة باستخدام ChainMap

توفر وحدة collections من المكتبة القياسية نوعًا متخصصًا من الحاويات يُسمى ChainMap. وهو فئة شبيهة بالقواميس، يُمكنك استخدامها لإنشاء عرض واحد قابل للتحديث من قواميس متعددة موجودة. سيظهر الكائن الناتج منطقيًا ويتصرف كقاموس واحد.

لا يدمج ChainMap قواميس الإدخال معًا، بل يُبقيها في قائمة داخلية. يمكن أن تحتوي قواميس الإدخال على مفاتيح مكررة. مع ذلك، لن يكون من الممكن الوصول إلا إلى النسخة الأولى من المفتاح المكرر في عمليات البحث والتحديث.

الآن، لنفترض أن لديك قاموسين يحتويان على فئات مختلفة من المنتجات وأسعارها. عليك تكرارهما معًا كقاموس واحد. لتحقيق ذلك، يمكنك إنشاء كائن ChainMap وتهيئته باستخدام قواميسك:

>>> from collections import ChainMap

>>> fruits = {"apple": 0.40, "orange": 0.35}
>>> vegetables = {"pepper": 0.20, "onion": 0.55}

>>> catalog = ChainMap(fruits, vegetables)
>>> catalog
ChainMap({'apple': 0.4, 'orange': 0.35}, {'pepper': 0.2, 'onion': 0.55})

>>> for product, price in catalog.items():
...     print(product, "->", price)
...
pepper -> 0.2
onion -> 0.55
apple -> 0.4
orange -> 0.35

بعد استيراد ChainMap من collections، عليك إنشاء كائن ChainMap بالقواميس التي تريد ربطها. بعد ذلك، يمكنك التكرار بحرية في الكائن الناتج كما تفعل مع أي قاموس عادي.

تتمتع كائنات ChainMap بنفس الواجهة مثل القواميس العادية، لذا يمكنك استخدام .()keys، و ()values، و .()items للتكرار عبر مكوناتها المختلفة.

عند استخدام ChainMap لتكرار عدة قواميس دفعةً واحدة، يجب أن تضع في اعتبارك أنه في حال وجود مفاتيح مكررة، فلن تتمكن من الوصول إلا إلى النسخة الأولى منها. خذ المثال التالي بعين الاعتبار:

>>> from collections import ChainMap

>>> for_adoption = {"dogs": 10, "cats": 7, "pythons": 3}
>>> vet_treatment = {"dogs": 4, "cats": 3, "turtles": 1}
>>> pets = ChainMap(for_adoption, vet_treatment)

>>> for pet, count in pets.items():
...     print(pet, "->", count)
...
...
dogs -> 10
cats -> 7
turtles -> 1
pythons -> 3

في هذا المثال، مرّت الحلقة فقط بالحالات الأولى من “dogs” و”cats”. لذلك، لن تحصل على بيانات من الحالات المكررة لهذه المفاتيح.

التكرار عبر سلسلة من القواميس باستخدام ()chain

توفر وحدة itertools دالة ()chain، التي يمكنها أخذ عدة كائنات قابلة للتكرار كوسائط وإنشاء مُكرِّر يُنتج عناصر من جميعها. للقيام بهذه المهمة، تبدأ الدالة ()chain بإنتاج عناصر من الكائن القابل للتكرار الأول حتى استنفاده، ثم تُنتج الدالة عناصر من الكائن القابل للتكرار التالي، وهكذا حتى استنفاد جميع كائنات الإدخال القابلة للتكرار.

يتيح لك هذا السلوك التكرار عبر قواميس متعددة في سلسلة تمر عبر جميع المفاتيح، حتى لو كانت هناك مفاتيح متكررة:

>>> from itertools import chain

>>> for_adoption = {"dogs": 10, "cats": 7, "pythons": 3}
>>> vet_treatment = {"dogs": 4, "cats": 3, "turtles": 1}
>>> pets = chain(for_adoption.items(), vet_treatment.items())

>>> for pet, count in pets:
...     print(pet, "->", count)
...
...
dogs -> 10
cats -> 7
pythons -> 3
dogs -> 4
cats -> 3
turtles -> 1

في الكود أعلاه، تُرجع دالة hain()chain مُكرِّرًا يُنتج عناصر من for_adoption وvet_treatment. تجدر الإشارة إلى أنه، بخلاف ChainMap، تُتيح لك دالة ()chain الوصول إلى جميع المفاتيح من قواميس الإدخال، حتى المُكرَّرة منها.

لديك الآن بعض الخبرة في التعامل مع القواميس باستخدام بايثون.


اكتشاف المزيد من بايثون العربي

اشترك للحصول على أحدث التدوينات المرسلة إلى بريدك الإلكتروني.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *

Scroll to Top

اكتشاف المزيد من بايثون العربي

اشترك الآن للاستمرار في القراءة والحصول على حق الوصول إلى الأرشيف الكامل.

Continue reading