المسارات
/
Python
Python
/
التمارين
/
إدارة المخزون
إدارة المخزون

إدارة المخزون

تمرين تعلّمي

مقدمة

القاموس (dict) في Python بنية بيانات تربط المفاتيح القابلة للتجزئة بـ_القيم_، ويُعرف في لغات البرمجة الأخرى باسم جدول التجزئة القابل لتغيير حجمه، أو خريطة التجزئة، أو المصفوفة الترابطية. والقواميس هي نوع الربط المدمج الوحيد في Python.

يجب أن تكون Keys قابلة للتجزئة وفريدة في القاموس كله. يمكن أن تشمل أنواع المفاتيح numbers أو str أو tuples (من قيم غير قابلة للتغيير). ولا يمكنها أن تحتوي على بنى بيانات قابلة للتغيير مثل lists أو dicts أو sets. وبدءًا من Python 3.7، أصبح ترتيب مفاتيح dict مضمونًا ليطابق ترتيب إدخال العناصر.

ويمكن أن تكون values من أي نوع أو بنية بيانات. كما يمكن للقيم أن تتداخل بشكل تعسفي، بحيث تشمل قوائم داخل قوائم، وقواميس فرعية، وبنى بيانات أخرى مخصصة أو مركّبة.

عند إعطاء key، تستطيع القواميس استرجاع value في زمن ثابت (في المتوسط) (بغض النظر عن عدد العناصر). وبالمقارنة مع البحث عن قيمة داخل list أو array (دون معرفة موضع index)، يستهلك dict ذاكرة أكبر بكثير، لكن استرجاعه سريع جدًا. وتكون القواميس مفيدة بشكل خاص حين تكون مجموعة العناصر كبيرة ويلزم الوصول إليها وتحديثها بشكل متكرر.

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

يمكن إنشاء القواميس بطرق كثيرة. وأبسط طريقتين هما استخدام المنشئ dict() أو الإعلان عن dict حرفي.

منشئ الصنف dict()

يمكن استخدام dict() (منشئ صنف القاموس) مع أي كائن قابل للتكرار من أزواج key وvalue، أو مع سلسلة من الوسائط <name>=<value>:

#Passing a list of key,value tuples.
>>> wombat = dict([('name', 'Wombat'),('speed', 23),('land_animal', True)])
{'name': 'Wombat', 'speed': 23, 'land_animal': True}


#Using key=value arguments.
>>> bear = dict(name="Black Bear", speed=40, land_animal=True)
{'name': 'Black Bear', 'speed': 40, 'land_animal': True}

القواميس الحرفية

يمكن أيضًا كتابة dict مباشرةً على هيئة قاموس حرفي، باستخدام الأقواس المعقوفة ({}) التي تُحيط بأزواج key : value:

>>> whale = {"name": "Blue Whale", "speed": 35, "land_animal": False}
{'name': 'Blue Whale', 'speed': 35, 'land_animal': False}

الوصول إلى القيم في القاموس

يمكنك الوصول إلى عنصر في القاموس باستخدام مفتاح بين الأقواس المربعة ([]). وإذا لم يكن key موجودًا في dict، يُرفع KeyError:

>>> bear["speed"]
40

>>> bear["color"]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'color'

يمكن تجنّب KeyError بالوصول إلى عنصر عبر الطريقة .get(<key>, <default value>):

>>> bear.get("color", 'not found')
'not found'

تغيير قيم القاموس أو إضافتها

يمكنك تغيير value الخاص بعنصر عبر الإسناد إلى المفتاح الخاص به:

#Assigning the value "Grizzly Bear" to the name key.
>>> bear["name"] = "Grizzly Bear"
{'name': 'Grizzly Bear', 'speed': 40, 'land_animal': True}

>>> whale["speed"] = 25
{'name': 'Blue Whale', 'speed': 25, 'land_animal': False}

ويمكن إضافة أزواج key:value جديدة بالطريقة نفسها:

# Adding a new "color" key with a new "tawney" value.
>>> bear["color"] = 'tawney'
{'name': 'Grizzly Bear', 'speed': 40, 'land_animal': True, 'color': 'tawney'}

>>> whale["blowholes"] = 1
{'name': 'Blue Whale', 'speed': 25, 'land_animal': False, 'blowholes': 1}

إزالة عناصر القاموس (عبر Pop)

يمكنك استخدام الطريقة .pop(<key>) لحذف عنصر من القاموس. وتزيل .pop() الزوج (key, value) وتُرجع value للاستخدام. ومثل .get()، تقبل .pop(<key>) وسيطًا ثانيًا (dict.pop(<key>, <default value>)) يُرجع إذا لم يُعثر على key. وهذا يمنع رفع KeyError:

#Using .pop() removes both the key and value, returning the value.
>>> bear.pop("name")
'Grizzly Bear'


#The "name" key is now removed from the dictionary.
#Attempting .pop() a second time will throw a KeyError.
>>> bear.pop("name")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'name'


#Using a default argument with .pop() will prevent a KeyError from a missing key.
>>> bear.pop("name", "Unknown")
'Unknown'

المرور على القاموس والتكرار خلاله

عند المرور على قاموس باستخدام for item in dict أو while item، سيتم التكرار على المفاتيح فقط بشكل افتراضي. ويمكنك الوصول إلى القيم داخل الحلقة نفسها باستخدام الأقواس المربعة:

>>> for key in bear:
>>>     print((key, bear[key])) #this forms a tuple of (key, value) and prints it.
('name', 'Black Bear')
('speed', 40)
('land_animal', True)

يمكنك أيضًا استخدام الطريقة .items()، التي تُرجع تلقائيًا صفوفًا من (key, value):

#dict.items() forms (key, value tuples) that can be unpacked and iterated over.
>>> for key, value in whale.items():
>>>     print(key, ":", value)
name : Blue Whale
speed : 25
land_animal : False
blowholes : 1

وبالمثل، ستُرجع الطريقة .keys() المفاتيح keys، وستُرجع الطريقة .values() القيم values.

التعليمات

في هذا التمرين، ستُدير نظام مخزون.

ينبغي تنظيم المخزون حسب اسم العنصر، وينبغي أن يتتبّع عدد العناصر المتاحة.

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

وأخيرًا، ستحتاج إلى تنفيذ دالة تُرجع جميع أزواج المفتاح والقيمة في مخزون معيّن على هيئة list من tuples.

1. إنشاء مخزون انطلاقًا من قائمة

نفّذ الدالة create_inventory(<input list>) التي تُنشئ «مخزونًا» من قائمة عناصر مُدخلة. ينبغي أن تُرجع dict يحتوي على اسم كل عنصر مقترنًا بكميته المقابلة.

>>> create_inventory(["coal", "wood", "wood", "diamond", "diamond", "diamond"])
{"coal":1, "wood":2, "diamond":3}

2. إضافة عناصر من قائمة إلى قاموس موجود

نفّذ الدالة add_items(<inventory dict>, <item list>) التي تضيف قائمة من العناصر إلى المخزون المُمرَّر:

>>> add_items({"coal":1}, ["wood", "iron", "coal", "wood"])
{"coal":2, "wood":2, "iron":1}

3. إنقاص العناصر من المخزون

نفّذ الدالة decrement_items(<inventory dict>, <items list>) التي تأخذ list من العناصر. ينبغي أن تطرح دالتك 1 من عدد العنصر في كل مرة يظهر فيها ذلك العنصر في list:

>>> decrement_items({"coal":3, "diamond":1, "iron":5}, ["diamond", "coal", "iron", "iron"])
{"coal":2, "diamond":0, "iron":3}

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

>>> decrement_items({"coal":2, "wood":1, "diamond":2}, ["coal", "coal", "wood", "wood", "diamond"])
{"coal":0, "wood":0, "diamond":1}

4. حذف مدخل بالكامل من المخزون

نفّذ الدالة remove_item(<inventory dict>, <item>) التي تحذف عنصرًا وعدده بالكامل من المخزون:

>>> remove_item({"coal":2, "wood":1, "diamond":2}, "coal")
{"wood":1, "diamond":2}

إذا لم يُعثر على العنصر في المخزون، ينبغي أن تُرجع الدالة المخزون الأصلي دون تغيير.

>>> remove_item({"coal":2, "wood":1, "diamond":2}, "gold")
{"coal":2, "wood":1, "diamond":2}

5. إرجاع المحتوى الكامل للمخزون

نفّذ الدالة list_inventory(<inventory dict>) التي تأخذ مخزونًا وتُرجع قائمة من صفوف (item, quantity). ينبغي أن تتضمن القائمة العناصر المتاحة فقط (أي التي كميتها أكبر من صفر):

>>> list_inventory({"coal":7, "wood":11, "diamond":2, "iron":7, "silver":0})
[('coal', 7), ('diamond', 2), ('iron', 7), ('wood', 11)]
تعديل عبر GitHub يفتح الرابط في نافذة أو علامة تبويب جديدة
Python Exercism

مستعد لبدء إدارة المخزون؟

سجّل في Exercism لتتعلّم وتتقن Python عبر 17 مفهومًا146 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.