العدادات Counters‎ في بايثون

من موسوعة حسوب


تقدم كائنات Counter (العدادات) أداة سريعة ومريحة لإجراء عمليات العدّ والحصول على المجموع.

العدّاد هو صنف متفرع من الصنف dict وظيفته عدّ الكائنات القابلة للتقطيع hashable. وهو عبارة عن مجموعة غير مرتّبة تكون فيها العناصر مخزّنة على هيئة مفاتيح قاموس ويخزّن تعداد هذه العناصر كقيم لتلك المفاتيح. يمكن للتعداد أن يكون عددًا صحيحًا وأن يكون صفرًا أو عددًا سالبًا. جدير بالذكر أن الصنف Counter مشابه للـ bags أو multisets في لغات البرمجة الأخرى.

البنية العامة

class collections.Counter([iterable-or-mapping])

يمكن عدّ العناصر من كائن مكرِّر iterable أو يمكن تهيئة (initialize) العدّ من كائن ربط mapping آخر (أو عدّاد آخر):

>>> c = Counter()                           # عدّاد جديد فارغ
>>> c = Counter('gallahad')                 # عدّاد جديد من كائن مكرِّر
>>> c = Counter({'red': 4, 'blue': 2})      # عدّاد جديد من كائن ربط
>>> c = Counter(cats=4, dogs=8)             # عدّاد جديد من معاملات مفتاحية

تمتلك كائنات العدّاد واجهة القواميس باستثناء أنّها تعيد القيمة 0 مقابل القيم التي لا تعثر عليها وذلك بدلًا من إطلاق الخطأ KeyError:

>>> c = Counter(['eggs', 'ham'])
>>> c['bacon']                       # تعداد عنصر غير موجود هو صفر
0

لا يؤدي تعيين القيمة 0 لتعداد عنصر معين إلى حذف ذلك العنصر من العدّاد، بل يجب استخدام del لحذف العنصر:

>>> c['sausage'] = 0                        # عنصر تعداده صفر
>>> del c['sausage']                        # حذف العنصر تمامًا

ملاحظة: هذا السلوك جديد في الإصدار 3.1 من اللغة.

توابع كائنات Counter

تقدّم العدادات ثلاثة توابع تضاف إلى التوابع المتاحة في القواميس:

التابع elements

يعيد هذا التابع كائنًا مكرِّرًا يتضمّن عناصر تتكرّر فيه حسب قيمة التعداد في كائن التعداد.

التابع most_common

يعيد التابع قائمة بالعناصر الأكثر تكرارًا إلى جانب عدد مرات التكرار.

التابع substract

يطرح التابع العناصر من الكائن المكرِّر أو من كائن mapping آخر (أو عداد آخر).

توابع تعمل بصورة مختلفة

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

التابع fromkeys

لا يمكن استخدام هذا التابع مع العدادات.

التابع update

عند استخدام هذا التابع يجري حساب العناصر من كائن مكرِّر أو تضاف من كائن ربط آخر (أو من عدّاد آخر).

ملاحظات

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

  • إنّ صنف العدّاد هو صنف متفرع عن القواميس ولكن دون وجود أيّ قيود على المفاتيح والقيم. ومع أنّ القيم معدّة لتكون أرقامًا تمثّل قيم التعدادات، إلا أنّه بالإمكان استخدام الأنواع الأخرى من القيم.
  • يتطلب التابع most_common()‎ أن تكون القيم قابلة للترتيب.
  • لإجراء العمليات في نفس المكان (مثل: c[key] += 1) فيجب أن يدعم نوع القيمة عمليتي الجمع والطرح. هذا يعني أنّ بالإمكان استخدام الكسور Fractions والأعداد العشرية ذات الفاصلة العائمة floats والأعداد العشرية decimals والأعداد السالبة. وينطبق ما سبق على التابعين update()‎ و subtract()‎ واللذين يسمحان باستخدام قيم سالبة أو صفرية في المدخلات والمخرجات.
  • صُمّمت توابع multiset لاستخدامها مع القيم الموجبة، ومع أنّه يمكن للمدخلات أن تكون صفرًا أو عددًا سالبًا، ولكن المخرجات تحتوي على قيم موجبة فقط. لا توجد قيود على الأنواع التي يمكن استخدامها مع هذه التوابع، ولكن يجب أن يدعم نوع القيمة عمليات الجمع والطرح والمقارنة.
  • يتطلب التابع elements()‎ وجود تعدادات من أعداد صحيحة، ويتجاهل الصفر والتعدادات السالبة.

أمثلة

يبين المثال التالي بعض الأساليب الشائعة في استعمال العدادات:

sum(c.values())                 # مجموع التعدادات
c.clear()                       # إعادة تعيين التعدادات
list(c)                         # قائمة بالعناصر الفريدة
set(c)                          # تحويل العداد إلى مجموعة
dict(c)                         # تحويل العداد إلى قاموس عادي
c.items()                       # (elem, cnt) تحويل العداد إلى قائمة من أزواج
Counter(dict(list_of_pairs))    # (elem ,cnt) التحويل من قائمة من أزواج
c.most_common()[:-n-1:-1]       # أقل العناصر تكرارًا
+c                              # حذف التعدادات السالبة والصفرية

يمكن استخدام هذه الكائنات لمعرفة عدد مرات تكرار كلمة ضمن قائمة معينة:

>>> cnt = Counter()
>>> for word in ['red', 'blue', 'red', 'green', 'blue', 'blue']:
...     cnt[word] += 1
>>> cnt
Counter({'blue': 3, 'red': 2, 'green': 1})

أو العثور على أكثر 10 كلمات تكرارًا في رواية Hamlet:

>>> import re
>>> words = re.findall(r'\w+', open('hamlet.txt').read().lower())
>>> Counter(words).most_common(10)
[('the', 1143), ('and', 966), ('to', 762), ('of', 669), ('i', 631),
 ('you', 554),  ('a', 546), ('my', 514), ('hamlet', 471), ('in', 451)]

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

>>> c = Counter(a=3, b=1)
>>> d = Counter(a=1, b=2)
>>> c + d                       # c[x] + d[x] إضافة عدادين إلى بعضهما البعض:‏
Counter({'a': 4, 'b': 3})
>>> c - d                       # طرح عداد من عداد آخر (الإبقاء على القيم الموجبة فقط)‏
Counter({'a': 2})
>>> c & d                       #  min(c[x], d[x]) التقاطع:‏
Counter({'a': 1, 'b': 1})
>>> c | d                       #  max(c[x], d[x]) الاتحاد:‏
Counter({'a': 3, 'b': 2})

تعدّ عمليات الجمع والطرح الأحادية Unary طرقًا مختصرة لإضافة عدّاد فارغ أو الطرح من عدّاد فارغ:

>>> c = Counter(a=2, b=-4)
>>> +c
Counter({'a': 2})
>>> -c
Counter({'b': 4})

ملاحظة: أصبحت عمليات الجمع والطرح الأحادية وعمليات المجموعات المتعدّدة في المكان ذاته مدعومة في الإصدار 3.3.

انظر أيضًا

  • كائنات namedtuple: :دالة مولِّدة factory function لإنشاء أصناف فرعية من tuple تتضمن حقولًا مسمّاة
  • كائنات deque: :حاوية شبيهة بالقوائم تمتاز بأدائها السريع في إضافة العناصر وحذفها في كلا الطرفين.
  • كائنات ChainMap: :صنف شبيه بالقواميس يستخدم لإنشاء عرض منفرد لعمليات ربط mapping متعددة
  • كائنات OrderedDict: :صنف فرعي من الصنف dict يمكنه تذكّر ترتيب العناصر عند إضافتها
  • كائنات defaultdict: :صنف فرعي من الصنف dict يستدعي دالة مولّدة تقدّم القيم المفقودة
  • كائنات UserDict: :تغليف حول كائنات القواميس لتسهيل عملية تفريع أصناف القواميس
  • كائنات UserList: :تغليف حول كائنات القوائم لتسهيل عملية تفريع أصناف القوائم
  • كائنات UserString: :تغليف حول كائنات السلاسل النصية لتسهيل عملية تفريع أصناف السلاسل النصية

مصادر