תעשו לי טובה ותעבדו עם Counter
- תוכן העניינים:
⊙ מה זה Counter?
קצת על שימוש בתת מחלקה בספרייה collections של פייתון, לספירת מופעים מהירה של ערכים בתוך מערך. בתמונה: פאי 🍰
לאחרונה יצא לי לעבור על הרבה קוד, עם הרבה קטעים שמנתחים סטטיסטיקות ממקורות מידע מסוימים, וכמובן איך לא - מציגים את המידע בדשבורדים עם גרפים ותרשימים ו'פאי' (תרשים עוגה).
ניקח כדוגמא אם יש לי מנגנון אנליטיקס, שאוסף מידע על המקורות מהם הגיעו גולשים לאתר. כשאני יתשאל את הדטבייס אני יקבל רשימת ביקורים באתר, ויצור ממנה מערך של המקורות. כזה, לדוגמא:
['facebook', 'facebook', 'google', 'twitter', 'google', 'facebook']
הצורך הוא ליצור רשימה של כל הערכים שמופיעים במערך, וספירה של כמות ההופעות של כל אחד מהם במערך. שיהיה תוצאה כזו:
[('facebook': 3), ('google': 2), ('twitter': 1)]
בקוד שראיתי, זה מומש בערך כך:
sources = ['facebook', 'facebook', 'google', 'twitter', 'google', 'facebook']
sources_sum = {}
for source in sources:
if source not in sources_sum:
sources_sum[source] = 1
else:
sources_sum[source] += 1
results = [(source, sources_sum[source]) for source in sources_sum]
print(results) # [('facebook', 3), ('google', 2), ('twitter', 1)]
מה זה Counter?
בספרייה collections
שהיא ספרייה מובנית בפייתון (3+) נמצא את Counter
. התיאור בתיעוד הוא:
A
Counter
is adict
subclass for counting hashable objects. It is a collection where elements are stored as dictionary keys and their counts are stored as dictionary values. Counts are allowed to be any integer value including zero or negative counts. TheCounter
class is similar to bags or multisets in other languages.
בפעולה הבסיסית שלו הוא פשוט עושה את זה: מוציא ממערך את מספר המופעים של כל ערך שבתוכו.
עם Counter
ניתן ליצור את התוצאה דלעיל בשורה אחת פשוטה (ולדעתי מאוד קריאה):
from collections import Counter
sources = ['facebook', 'facebook', 'google', 'twitter', 'google', 'facebook']
results = dict(Counter(sources)).items()
print(results) # dict_items([('facebook', 2), ('google', 2), ('twitter', 1)])
Counter
מחזיר אובייקט Counter
שממנו ניתן ליצור dict
- ממנו ניתן לחלץ מערך של tuples
- כל המפתחות והערכים שלהם עם ידי המתודה items()
.
אני בטוח שמבחינת ביצועים יהיו יתרונות לטובת ה-Counter
וזו עוד סיבה להמשתמש בו כמובן, אבל מה שתפס אותי זו הקריאות והקוד הקצר.
ריפקטורינג של קטעים כאלה, יכול לקצר קטעי קוד ארוכים ומפרכים, ולתת למפתחים חדשים שעובדים על הקוד להבין יותר מה הם עושים.
יש ל-Counter
עוד הרבה יתרונות ומתודות מעניינות (כמו האופציה להשוואה בין שני Counters
- שזה משווה את התוכן שלהם, האופציה להוספה של Counter
ל-Counter
כך שבעצם נוצר Counter
חדש עם שילוב של הערכים משני ה-Counters
, המתודה ()most_common
שמביאה במהירות את הערך הגבוה ביותר ב-Counter
ועוד) את הכול אפשר ללמוד מהתיעוד הברור, אני מצרף בסוף גם כמה בלוג פוסטים טובים שקראתי עליו.
אז מי כאן שכותב פייתון, ויכתוב בזכותי עוד Counter
בעולם - והיה זה שכרי.
יום טוב וקוד טוב 😉
כמה מראי מקומות בסיסיים ל-Counter
:
- דבר ראשון כמובן התיעוד הרשמי
- בלוג / מדריך מצוין ב-realpython