freeCodeCamp/guide/arabic/computer-science/data-structures/dictionaries/index.md

214 lines
12 KiB
Markdown
Raw Normal View History

---
title: Dictionaries
localeTitle: قواميس
---
## قواميس
لنفترض أن لدينا قائمة متجانسة. نريد احتساب عدد المرات التي يحدث فيها كل عنصر في القائمة. كيف يمكننا القيام بذلك ، دون استخدام أساليب بايثون المدمجة مثل العد أو العداد من وحدة بايثون؟ بحث في Google عن "كيفية حساب تواجدات عنصر ما في قائمة؟" ستقوم بإرجاع إجابات Stack Overflow التي توجهك إلى طريقة الفرز ووحدة المجموعات ، ولكن لأغراض التعلم ، دعنا نحاول حل المشكلة بدون استخدام هذه الأدوات.
إليك القائمة التي سنعمل معها:
```python
ice_cream = ["strawberry",
"vanilla",
"vanilla",
"chocolate",
"chocolate",
"chocolate",
"banana",
"rum raisin",
"banana"]
```
يعطي هذا الرمز ، الذي يستخدم متداخلاً لحلقات ، الإجابة الصحيحة ، وتخزين الإجابة في قائمة "العد":
```python
count = []
for flavor in ice_cream:
found = False
for entry in count:
if entry[0] == flavor:
entry[1] += 1
found = True
if not found:
count.append([flavor, 1])
# Print.
for (entry, total) in count:
print (entry, total)
```
على الرغم من أن هذا الرمز يعطي الإجابة الصحيحة ، إلا أنه يوجد شيئان خاطئان به. أولاً ، إنها معقدة. كلما زاد عدد الحلقات المتداخلة التي يحتوي عليها البرنامج ، كلما كان من الصعب فهمها وإصلاحها وتوسيعها. علاوة على ذلك ، فهو غير فعال. قد لا يكون هذا مشكلة في هذا المثال الصغير ، ولكن تخيل قائمة تحتوي على آلاف أو ملايين العناصر. إن مسح قائمة الإدخالات في كل مرة نقوم فيها بملاحظة تستغرق وقتًا طويلاً للغاية ، بغض النظر عن سرعة الكمبيوتر. هذا موضوع تم تناوله بشكل كامل عند دراسة موضوعات مثل التدوين الكبير O ومقارنة خوارزميات البحث والفرز.
والإجابة الأفضل هي استخدام بنية بيانات أخرى تُعرف باسم **قاموس** أو **خريطة** . هيكل البيانات هذا عبارة عن مجموعة _غير قابلة للتجزئة ومتكررة_ من أزواج _المفاتيح / القيمة_ . فكر في قاموس مثل دليل الهاتف ، حيث يكون المفتاح هو اسم الشخص ، والقيمة هي رقم الهاتف. تشكل المفاتيح في القاموس مجموعة ، مما يعني أنها يمكن أن تظهر مرة واحدة فقط ، ولا يمكن تغييرها (فهي غير قابلة للتغيير) ، على الرغم من أنه يمكن تغيير القيم المرتبطة بالمفتاح.
يتم إنشاء القواميس عن طريق وضع أزواج المفاتيح / القيم داخل الأقواس. للحصول على القيمة المرتبطة بمفتاح ، تضع المفتاح بين أقواس مربعة.
فيما يلي بعض أمثلة التعليمات البرمجية:
```python
ice_cream = {'chocolate' : 3, 'strawberry' : 1}
print (ice_cream)
>> {'chocolate' : 3, 'strawberry' : 1}
print (ice_cream['strawberry'])
>> 1
```
لاختبار ما إذا كان المفتاح موجودًا في أحد القواميس ، استخدم k في d:
```python
ice_cream = {'chocolate' : 3, 'strawberry' : 1}
if 'chocolate' in ice_cream:
print ('chocolate is in the list')
...
del ice_cream['chocolate']
if 'chocolate' in ice_cream:
print ('oops: why is chocolate still there?')
```
**تحديث والعضوية** لتحديث القواميس ، ما عليك سوى تعيين قيمة للمفتاح. إذا كان المفتاح موجودًا بالفعل في القاموس ، فسيؤدي ذلك إلى تغيير القيمة المرتبطة به.
إذا لم يكن المفتاح موجودًا ، فيتم إضافته بالإضافة إلى القيمة:
```python
ice_cream = {}
ice_cream['chocolate'] = 33
ice_cream['vanilla'] = 999 # oops
print (ice_cream)
>> {'chocolate' : 33, vanilla' : 999}
ice_cream['vanilla'] = 9
print (ice_cream)
>> {'chocolate' : 33, vanilla' : 9}
```
استخدم _del d \[k\]_ ، لإزالة إدخال من قاموس ، حيث _d_ هو اسم القاموس و _k_ هو المفتاح الذي يتم إزالته. يمكن إزالة الإدخالات الموجودة فقط؛ محاولة إزالة واحدة غير موجودة يسبب خطأ:
```python
ice_cream = {'chocolate' : 33, vanilla' : 9}
del ice_cream['chocolate']
print (ice_cream)
>> {'vanilla' : 9}
del ice_cream['strawberry']
>> Traceback (most recent call last):
File "<stdin>", line 5, in <module>
KeyError: 'strawberry'
```
**الحلقات** بما أن القواميس عبارة عن مجموعات (جنباً إلى جنب مع القوائم ، والصفوف ، والمجموعات) ، فإننا سنرغب في تكرار حلقاتها محتويات. نقوم بذلك من خلال حلقة for ، والتي تقوم بتعيين كل من المفاتيح في القاموس إلى متغير الحلقة بدوره:
```python
ice_cream = {'chocolate' : 183,
'vanilla' : 71,
'strawberry' : 63,
'banana', 1}
for flavor in ice_cream:
print (flavor, ice_cream[flavor])
>> 'banana' 1
'vanilla' 71
'chocolate' 183
'strawberry' 63
```
كما هو الحال مع العناصر المحددة ، تقوم بايثون بتكرار أكثر من الإدخالات في القاموس بترتيب عشوائي. ليس هناك ما يضمن أن ينظر إليها أبجديا أو بالترتيب ، تم إضافتها إلى القاموس. لاحظ ، بالمناسبة ، أن التكرار فوق القواميس يختلف قليلاً عن التكرار على القوائم. عندما تقوم بايثون بتكرار أكثر من قائمة ، يتم تعيين القيم في القائمة للمتغير المتكرر. عندما تقوم الحلقات عبر قاموس ، من ناحية أخرى ، فإنه يعيّن المفاتيح. اختار مصممو بيثون القيام بذلك بسبب:
* حلقات على قوائم من القائمة ليست مثيرة للاهتمام ، لأن سيحصل البرنامج دائمًا على التسلسل 0 ، 1 ، 2 ، ... ؛ و
* من السهل جدًا الانتقال من مفتاح القاموس إلى القيمة المرتبطة من أن تأخذ القيمة والعثور على المفتاح المرتبط.
**طرق القاموس** القواميس هي كائنات ، تمامًا مثل القوائم ، الصفوف والمجموعات. بعض طرق القاموس الشائعة هي:
* _d.clear ()_ - مسح القاموس
* _d.get (x، 99)_ - لعرض القيمة المرتبطة بمفتاح ، أو قيمة افتراضية في حالة عدم وجود المفتاح.
* _d.keys ()_ - مفاتيح العودة
* _d.items ()_ - قائمة العودة لأزواج المفاتيح ، القيمة
* _d.values ()_ - قيم الإرجاع كقائمة ، قد لا تكون القيم فريدة
* _d.update ()_ - تحديث القاموس مع محتويات آخر
أحد الاستخدامات الشائعة للعناصر هو إجراء حلقة فوق المفاتيح والقيم في القاموس معًا: لـ (key، value) في dictionary.items (): ... تفعل شيئا مع المفتاح والقيمة ...
هذا غير فعال للقواميس الكبيرة لأن العناصر () في الواقع يبني قائمة من أزواج (مفتاح ، قيمة). وهناك طريقة مشابهة تدعى _iteritems () تقوم_ بتسليم هذه الأزواج مرة واحدة تلو الأخرى عند الطلب: لـ (key، value) في dictionary.iteritems (): ... تفعل شيئا مع المفتاح والقيمة ...
لنعد إلى المثال الأصلي - كيف نحسب عدد العناصر في قائمة ice\_cream باستخدام القاموس؟
```python
# Count all the flavors.
ice_cream = ["strawberry",
"vanilla",
"vanilla",
"chocolate",
"chocolate",
"chocolate",
"banana",
"rum raisin",
"banana"]
count = {}
for flavor in ice_cream:
if flavor in count:
count[flavor] = count[flavor] + 1
else:
count[flavor] = 1
# Print.
for b in count:
print (b, count[b])
```
للقيام بذلك ، نقوم بإنشاء قاموس فارغ في البداية. في كل مرة يتم فيها التكرار عبر قائمة ice\_cream ، نتحقق من ذلك لمعرفة ما إذا كانت النكهة موجودة بالفعل في قاموس العدد. إذا كان كذلك ، نضيف واحدة إلى حسابها. إذا لم يكن الأمر كذلك ، فسنضيف الاسم إلى القاموس ذي القيمة 1.
يمكننا اختصار هذا البرنامج قليلا باستخدام الطريقة _dict.get ()_ . هذا يعيد إما القيمة المرتبطة بمفتاح أو بعض القيمة الافتراضية التي نقدمها. في هذه الحالة ، نحصل إما على عدد المرات التي رأينا فيها بالفعل نكهة أو صفر ، أضف واحدًا إلى أي قيمة ترجعها الطريقة ، وتخزينها مرة أخرى في القاموس:
```python
# Count all the flavors.
count = {}
for flavor in ice_cream:
count[flavor] = count.get(flavor, 0) + 1
# Print.
keys = count.keys()
keys.sort()
for b in keys:
print (b, count[b])
# Print.
for key in sorted(count):
print (key, count[key])
```
لاحظ أننا نستخدم طريقتين منفصلتين لطباعة المفتاح والقيمة: يستخدم أحدهما طريقة التصنيف في Python ، والآخر لا يفعل ذلك.
إذا أردنا طباعة النكهات بالترتيب ، نحتاج إلى **عكس القاموس** . هذا يعني أننا بحاجة إلى استخدام القيم كمفاتيح ، والمفاتيح كقيم. نظرًا لعدم وجود ضمان بأن القيم فريدة ، نحتاج إلى اتخاذ خطوات لتجنب _التصادمات_ .
الحل هو استخدام نوع من التجميع ، مثل قائمة ، لتخزين قيم القاموس المقلوب. إذا انتقلنا إلى هذا المسار ، فسيكون معكوس القاموس المعروض سابقًا {1: \['a'، 'b'، 'c'\]}. إليك برنامج لفعل ما نريد:
`ice_cream = ["strawberry",
"vanilla",
"vanilla",
"chocolate",
"chocolate",
"chocolate",
"banana",
"rum raisin",
"banana"]
# Count all the flavors.
count = {}
for flavor in ice_cream:
count[flavor] = count.get(flavor, 0) + 1
# Invert the dictionary.
freq = {}
for (flavor, times) in count.items():
if times in freq:
freq[times].append(flavor)
else:
freq[times] = [flavor]
# Print.
for key in freq:
for flavor in sorted(freq[key]):
print (key,":", " ", flavor)
`
#### معلومات اكثر: