מילונים (dict)#
מוטיבציה למילונים#
טקסט המופיע למטה בסגול מציין קטעים המופיעים בסרטון
ניתן להיעזר בו כדי לחזור על התכנים או לעיין בהם שוב.
נכיר כעת מבנה נתונים נוסף - מילון.
נתחיל מלהסביר למה אנחנו בכלל צריכים עוד מבנה נתונים.
נזכיר כי ברשימות יש משמעות לסדר של האיברים.
למעשה, מאחורי הקלעים, רשימה שמורה כקו ישר של תאים בזיכרון, כאשר כל תא מחזיק ערך מסוים.
כשרוצים להגיע לאיבר מסוים לפי מיקום, זה נוח - יש לכל תא יש כתובת, וניתן “לקפוץ” ישר לאינדקס הרצוי ולקרוא את הערך. התהליך הזה קורה כמעט מיד - באמצעות “קפיצה” מתחילת הרשימה למיקום הרצוי לפי האינדקס.
אם נרצה להוסיף איבר חדש בסוף הרשימה (על-ידי append) - נקפוץ פשוט לסוף הרשימה ונשים את האיבר בתא פנוי בסופה.
הבעיה מתחילה כשמנסים להכניס איבר לתחילת הרשימה. כדי לשמור על הסדר, כל האיברים הקיימים צריכים לזוז מקום אחד קדימה, כלומר, נצטרך להזיז כל איבר מקום אחד בזכרון. אם קיימים לנו n איברים ברשימה, נצטרך לבצע n הזזות. זה כבר ייקח יותר זמן.
במילים אחרות, על מנת להשלים את הפעולה שלנו - הכנסת איבר חדש לתחילת הרשימה - נדרש לבצע מספר גבוה של פקודות, או צעדים.
נשים לב למספר נקודות חשובות שבאות לידי ביטוי בדוגמא לעיל:
על מנת להשלים את ביצוען של פעולות שונות נדרש מספר שונה של צעדים .
מספר הצעדים הדרושים להשלמתן של פעולות מסוימות תלוי בקלט (במקרה לעיל, אורך הרשימה)
אם מניחים שכל צעד לוקח אותו זמן – פעולות עם יותר צעדים יארכו יותר זמן.
נבחן כעת דוגמא נוספת: חיפוש איבר ברשימה.
על מנת לבדוק אם מספר מסוים נמצא ברשימת מספרים כלשהי, יהיה עלינו לעבור על כל האיברים ברשימה אחד-אחד ולבדוק אם האם מצאנו את המספר המבוקש.
בדוגמא זו, עבור רשימה בגודל n, יידרשו n צעדים לכל היותר על מנת להשלים את הפעולה. כלומר, גם פעולת חיפוש ברשימה אינה קלה, במיוחד כאשר מדובר ברשימה המכילה מספר רב של איברים.
עצרו וחשבו
מדוע בדוגמת הכנסת איבר לראש הרשימה נדרשות תמיד n הזזות, אך בדוגמת החיפוש נדרשים n צעדים לכל היותר?
שימו לב
בהמשך הקורס נתעמק בדרכים יעילות יותר ופחות לחפש איברים ברשימה תחת הנחות מסוימות, כמו סדר האיברים הרשימה.
לסיכום, רשימות הן מבנה נוח וגמיש, אבל יש פעולות מסוימות (כמו הכנסת איבר בתחילת הרשימה או חיפוש איבר) שבו מבנה נתונים זה פחות יעיל, דבר שיבוא לידי ביטוי ככל שהרשימה תגדל.
כלומר, אם היינו רוצים לשמור את המידע שלנו בדרך שבה קל להוסיף וגם קל לחפש, נרצה להשתמש במבנה נתונים אחר.
ואכן, קיים מבנה נתונים שמתאים בדיוק למקרים כאלו - הטיפוס מילון (dictionary, או dict בפייתון). מצד שני, במילון לא ניתן לשלוט בסדר האיברים.
בהמשך היחידה, נדגים כיצד נוכל באמצעות מילונים לבצע בצורה יעילה יותר חלק מהפעולות שמסורבל לבצע על רשימות.
מילונים בפייתון#
טקסט המופיע למטה בסגול מציין קטעים המופיעים בסרטון
ניתן להיעזר בו כדי לחזור על התכנים או לעיין בהם שוב.
אז בואו נדבר כעת על מילונים בפייתון
בניגוד לרשימות, שבהן ניגשים לאיברים לפי המיקום שלהם, במילון הגישה נעשית ישירות לפי מפתח (key). כלומר, אם יש לנו מפתח מסוים, נוכל למצוא את הערך המשויך אליו במהירות ובקלות.
או במילים אחרות, מילון הוא מבנה נתונים שמאפשר לגשת למידע במהירות באמצעות התאמה של מפתח לערך.
נשים לב שהזכרנו פה שני יתרונות שיש למילון על פני רשימה:
המפתחות במילון יכולים להיות בעלי משמעות, שלאו דווקא קשורים לסדר האיברים במבנה הנתונים שלנו. כלומר, מילון יכול להתאים לשמירת נתונים שלאו דווקא צריכים להשמר בסדר כלשהו.
בנוסף, מילון ניגש במהירות לערך לפי מפתח. הודות לאופן שבו הוא בנוי, הגישה לערך לפי מפתח היא מאוד יעילה, הרבה יותר מאשר חיפוש איבר-איבר ברשימה, שם הגישה מתבצעת לפי מיקום האיבר.
כדי להמחיש, נחשוב על דוגמא בה אנו רוצים לקרוא למשה, חברנו לספסל הלימודים.
במקום לעבור כיסא אחר כיסא ולבדוק אם משה יושב שם, קל יותר פשוט לקרוא למשה בשמו.
אבל מה יקרה אם קיימים מספר סטונדטים בכיתה בשם “משה”?
למעשה במילון לכל מפתח יש ערך יחיד שמקושר אליו, ואם ננסה להוסיף שוב את אותו המפתח – הערך הקודם פשוט יוחלף (בדומה להשמה חוזרת למשתנה קיים).
לכן, בדוגמא לעיל, נוכל אולי להשתמש בצירוף של שם פרטי ושם משפחה בתור מפתח (אם מניחים כי אין שני סטונדטים בעלי אותו שם פרטי ושם משפחה).
לחלופין, נוכל כמובן להשתמש בתעודת זהות. זה כמובן יהיה תקין (מפני שלכל סטודנט יש מספר תעודת זהות ייחודי), אך פחות אינטואיטיבי.
במילים אחרות, המפתח חייב ייחודי. בנוסף, נעדיף מפתחות שהם שנוח לנו לעבוד איתם.
נדגיש שוב שבניגוד לרשימה, באופן עקרוני במילון לא ניתן לשלוט בסדר האיברים.
כדאי לדעת!
בפועל, החל מפייתון 3.7, הסדר בdict נשמר לפי סדר הכנסת המפתחות והערכים למילון, אך לא נניח סדר כזה במסגרת הקורס.
שימוש בסיסי במילון בפייתון#
כדי להדגים כיצד משתמשים במילוני בפייתון, נממש את המילון המופיע בתמונה הבאה:
בדומה לרשימות וטאפלים, גם מילונים עטופים בסוגריים - במקרה של מילון מדובר בסוגריים מסולסלים.
לדוגמא, מילון ריק יראה כך:
d = {}
אך בניגוד לרשימות וטאפלים, כל אלמנט במילון הוא למעשה זוג של מפתח וערך.
המפתח והערך מופרדים ע”י נקודותיים (:) וכל זוג של מפתח וערך מופרד באמצעות פסיק (,).
לדוגמא, מימוש של המילון המופיע בתמונה ייראה כך:
{"Avi": 90, "Moshe": 80, "Adam": 70}
{'Avi': 90, 'Moshe': 80, 'Adam': 70}
שימו לב שבאופן עקרוני יכולנו לשמור בדיוק את אותו המידע גם באמצעות מבני נתונים שכבר למדנו. לדוגמא, באמצעות רשימה של טאפלים:
[("Avi", 90), ("Moshe", 80), ("Adam", 70)]
[('Avi', 90), ('Moshe', 80), ('Adam', 70)]
נממש כעת קוד המדפיס ציון של סטודנט השמור במשתנה name תוך שימוש בשני סוגי מבני הנתונים הללו ונשווה בין המימושים.
נתחיל ממימוש המניח כי המידע מיוצג כרשימה של טאפלים:
name = "Moshe"
studs = [("Avi", 90), ("Moshe", 80), ("Adam", 70)]
for cur_stud in studs:
if cur_stud[0] == name:
print(cur_stud[1])
80
כעת נראה מימוש המניח כי ציוני הסטונדטים שמורים במילון:
name = "Moshe"
studs = {"Avi": 90, "Moshe": 80, "Adam": 70}
print(studs[name])
80
עצרו וחשבו
כמה פעמים נצטרך לגשת לרשימה במקרה הגרוע ביותר?
כלומר, ניתן לגשת לכל מפתח שקיים במילון ולקבל את הערך שלו, באמצעות סוגריים מרובעים.
שימו לב כי שני המימושים מדפיסים בסופו של דבר את אותה התוצאה, אך המימוש השני עדיף במספר מובנים:
הקוד יותר יעיל - כלומר, נדרשות פחות גישות למבנה הנתונים שלנו
בנוסף, הקוד יותר קריא - הוא גם קצר יותר וגם מובן יותר מהמימוש שכתבנו באמצעות רשימות
שימו לב
מה היה קורה אם היינו מנסים לגשת למפתח שלא קיים במילון?
בדומה לשגיאת index out of range שקיבלנו ברשימות כאשר האינדקס אינו קיים, גם במקרה של מפתח לא קיים נקבל שגיאה מתאימה key error, כלומר, המפתח אינו קיים.
studs = {"Avi": 90, "Moshe": 80, "Adam": 70}
print(studs["Haim"])
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
Cell In[8], line 2
1 studs = {"Avi": 90, "Moshe": 80, "Adam": 70}
----> 2 print(studs["Haim"])
KeyError: 'Haim'
כדי שגישה למפתח לא קיים תגרום לשגיאה, היינו רוצים לוודא שמפתח אכן קיים במילון לפני שננסה לגשת לערך שלו.
ומסתבר, שיש כזו אפשרות, על-ידי המילה השמורה in שכבר ראינו ברשימות ומחרוזות.
במקרה של מילונים, הפקודה k in d תחזיר True אם המפתח k קיים במילון d, וFalse אחרת.
נראה כעת דוגמא לשימוש במילה in במילון הסטונדטים שלנו:
studs = {"Avi": 90, "Moshe": 80, "Adam": 70}
print("Johnny" in studs)
print("Avi" in studs)
print(80 in studs) # 80 is a value, not a key, so that will be False.
False
True
False
דרך נוספת להחזיר ערכים בצורה בטוחה היא באמצעות המתודה get.
מתודה זו מאפשרת לנו לגשת לערך של מפתח במילון מבלי לגרום לשגיאה אם המפתח אינו קיים.
אם המפתח קיים במילון - המתודה תחזיר לנו את הערך שמקושר למפתח.
אם המפתח לא קיים במילון, המתודה תחזיר לנו את ערך ברירת מחדל - None.
studs = {"Avi": 90, "Moshe": 80, "Adam": 70}
print(studs.get("Avi")) # The key exists, so we'll get the value
print(studs.get("Johnny")) # The key doesn't exist, so we'll get the default - None
90
None
בנוסף, אפשר לשנות את ערך ברירת המחדל — פשוט מוסיפים אותו כארגומנט השני בפונקציה get.
לדוגמא, בקוד הבא תוחזר המחרוזת "student not found" אם הסטודנט אינו קיים.
studs = {"Avi": 90, "Moshe": 80, "Adam": 70}
print(studs.get("Johnny", "Student not found")) # The key doesn't exist, so we'll get the default - "not found"
Student not found
כעת נרצה להוסיף סטודנט חדש למילון, כלומר, נרצה להכניס זוג של מפתח-ערך נוסף.
נעשה זאת על ידי השמת הערך במילון לפי המפתח הנדרש:
d[key] = value
לדוגמא, בקוד הבא אנו נוסיף את ג’וני למילון הסטודנטים שלנו.
print(studs)
studs["Johnny"] = 95
print(studs)
{'Avi': 90, 'Moshe': 80, 'Adam': 70}
{'Avi': 90, 'Moshe': 80, 'Adam': 70, 'Johnny': 95}
אם נבצע השמה לd[k] עבור מפתח k שכבר היה במילון, אנחנו נעדכן את הערך הקיים - כלומר, נדרוס אותו ונכניס ערך חדש במקומו.
לדוגמא, הקוד הבא מעדכן את ציון של משה ל90:
print(studs)
studs["Moshe"] = 90
print(studs)
{'Avi': 90, 'Moshe': 80, 'Adam': 70, 'Johnny': 95}
{'Avi': 90, 'Moshe': 90, 'Adam': 70, 'Johnny': 95}
תרגול#
עכשיו גם אתם תממשו מילון ציונים.
צרו מילון ריק בשם
grades, והדפיסו אותו למסך.
# Write your code here
עדכנו את
gradesכך שיכיל ציונים של שלושה סטודנטים:“Amir” קיבל ציון 95
“Michal” קיבלה ציון 97
“Hagai” קיבל ציון 82.
הדפיסו את המילון למסך.
רמז
האם תעדיפו לחפש סטודנט ולבדוק מה הציון שלו? או לחפש ציון ולבדוק איזה סטודנט קיבל אותו?
# Write your code here
הדפיסו את הציון של מיכל.
# Write your code here
בדקו אם ל”Maya” יש ציון.
אם כן, הדפיסו את הציון שלה.
אם לא, הדפיסו הודעה “Maya not found”.
# Write your code here
הוסיפו למילון את “Maya” שקיבלה ציון 76. הדפיסו שוב את המילון וודאו שמאיה מופיעה בו.
# Write your code here
חגי עשה מועד ב’ והעלה את הציון שלו ל100! עדכנו את הציון שלו בהתאם. הדפיסו שוב את המילון כדי לוודא שהציון המעודכן של חגי מופיע.
# Write your code here
לחצו כאן כדי לצפות בפתרון
# 1
grades = {}
print(grades)
# 2
grades["Amir"] = 95
grades["Michal"] = 97
grades["Hagai"] = 82
print(grades)
# 3
print(grades["Michal"])
# 4
if "Maya" in grades:
print(grades["Maya"])
else:
print("Maya not found")
# 5
grades["Maya"] = 76
print(grades)
# 6
grades["Hagai"] = 100
print(grades)
עד כה הדגמנו שימוש בסיסי במילון. כעת נרחיב את סט הכלים שלנו עם פעולות מתקדמות יותר.
מפתחות מורכבים#
ראינו שמפתחות במילון הם ייחודיים, ולכן שינוי ערך של מפתח קיים יעדכן (או ידרוס) את הערך הקודם.
studs = {"Avi": 90, "Moshe": 80, "Adam": 70}
print(studs)
studs['Moshe'] = 90
print(studs)
{'Avi': 90, 'Moshe': 80, 'Adam': 70}
{'Avi': 90, 'Moshe': 90, 'Adam': 70}
אבל נניח, כפי שהצגנו בדוגמא המקורית, כי ישנם שני סטודנטים בשם משה - בעלי שם משפחה שונה: משה כהן ומשה לוי.
מובן כי כעת לא נוכל להסתפק בשם הפרטי בלבד כמפתח, מכיוון שמפתח (במקרה זה השם הפרטי משה) אינו יכול להופיע יותר מפעם אחת.
כדי לפתור את הבעיה, נוכל להוסיף את שם המשפחה למפתח, בנוסף לשם הפרטי.
ננסה תחילה לממש רעיון זה ע”י הגדרת המפתח כרשימה המכילה שם פרטי ושם משפחה.
studs = {['Moshe', 'Cohen']: 90, ['Moshe', 'Levi']: 90}
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[21], line 1
----> 1 studs = {['Moshe', 'Cohen']: 90, ['Moshe', 'Levi']: 90}
TypeError: unhashable type: 'list'
הנסיון שלנו לא הצליח. מדוע קיבלנו שגיאה?
מסתבר שמפתח חייב להיות immutable.
מכיוון שרשימה היא mutable, היא איננה יכולה להיות מפתח.
אז מה אפשר לעשות? איזה טיפוס הוא ממש כמו רשימה, אבל immutable?
ניתן להשתמש ב־tuples בתור מפתחות!
studs = {'Avi': 90, ('Moshe', 'Cohen') : 90, ('Moshe', 'Levi') : 80, 'Adam': 70}
print(studs)
{'Avi': 90, ('Moshe', 'Cohen'): 90, ('Moshe', 'Levi'): 80, 'Adam': 70}
תרגול:
ממשו פונקציה המקבלת את מילון סטודנטים ושם הסטונדט ומחזירה את הציון של הסטודנט.
שימו לב ששם הסטודנט יכול להיות מחרוזת (שם פרטי בלבד) או טאפל (המכיל שם פרטי ושם משפחה). על הפונקציה לעבוד ב2 המקרים הללו.
def foo(ds, name):
pass
## Write your code here
name=("Moshe", "Cohen")
studs = {'Avi': 90, ('Moshe', 'Cohen') : 90, ('Moshe', 'Levi') : 80, 'Adam': 70}
foo(studs, name)
תצוגות מילון (Dictionary Views)#
בפייתון קיימות מתודות שמחזירות תצוגות מילון איטרביליות. כלומר, ניתן לעבור עליהן בלולאות, ולבדוק שייכות של מפתח או ערך עם in.
בנוסף תצוגות אלו הן דינמיות כלומר, הן משתנות אוטומטית כאשר המילון משתנה.
נתמקד תחילה במתודה items, שמחזירה את את כל הזוגות של המפתחות והערכים במילון.
שימוש נפוץ במתודה items הוא בלולאות בהן נרצה לעבור על כל הזוגות של המפתחות והערכים במילון.
למשל, אם נרצה להדפיס את כל השמות והציונים של מילון הסטודנטים שלנו שורה אחר שורה, נוכל לעשות זאת כך:
studs = {"Avi": 90, "Moshe": 80, "Adam": 70}
for key, value in studs.items():
print(key, ":", value)
Avi : 90
Moshe : 80
Adam : 70
בנוסף, קיימות עוד שתי תצוגות נפוצות: keys ו-values, המחזירות את המפתחות והערכים של המילון, בהתאמה:
print("All keys:")
for key in studs.keys():
print(key)
All keys:
Avi
Moshe
Adam
print("All values:")
for value in studs.values():
print(value) # No default way to get the key.
All values:
90
80
70
שימו לב
בד”כ נעדיף לא למשתמש ב()values, על מנת לעבור על ערכי המילון מכיוון שבדרך זו אנו עושים מעבר לא יעיל על ערכי המילון ומאבדים את הקשר של ערכים עם המפתחות שלהם (זכרו כי ניגשים לכל ערך במילון באמצעות מפתח!)
מתודות של מילונים#
טקסט המופיע למטה בסגול מציין קטעים המופיעים בסרטון
ניתן להיעזר בו כדי לחזור על התכנים או לעיין בהם שוב.
נלמד כעת על מספר מתודות שימושיות של מילונים.
העתקת מילון ()d.copy
המתודה יוצרת עותק של המילון המקורי עם אותם מפתחות וערכים.
מבנה העותק המשוכפל יהיה זהה למבנה המילון המקורי, או הוא אינו אותו האובייקט: שינוי במבנה (הוספה/הסרה של מפתחות) במילון החדש לא ישפיע על המקורי.
מאחרוי הקלעים, ההעתקה מתבצעת ע”י השמת הערכים של המילון המקורי במילון המשוכפל. במילים אחרות, הערכים במילון אינם משוכפלים. לכן, שינוי ערך mutable (כמו רשימה), במילון המקורי ישנה את ערכו גם במילון ששוכפל.
על מנת להדגים זאת, נחזור לדוגמא של מילון הסטודנטים שלנו, כאשר הערכים בו כעת יהיו רשימת ציונים, המכילים ציון בודד.
studs = {"Avi": [90], "Moshe": [80], "Adam": [70]}
תחילה, נשכפל את המילון:
studs_2 = studs.copy()
נוסיף כעת סטודנט חדש למילון המשוכפל, ונדפיס את 2 המילונים.
הקוד המלא יראה כך:
studs = {"Avi": [90], "Moshe": [80], "Adam": [70]}
studs_2 = studs.copy()
studs_2["Johnny"] = [60]
print(studs)
print(studs_2)
{'Avi': [90], 'Moshe': [80], 'Adam': [70]}
{'Avi': [90], 'Moshe': [80], 'Adam': [70], 'Johnny': [60]}
כפי שניתן לראות, הסטודנט החדש התווסף רק במילון המשוכפל.
כעת נוסיף למשה את הציון 100 במילון המשוכפל. כלומר, כעת יהיו למשה שני ציונים:
studs_2["Moshe"].append(100)
print(studs)
print(studs_2)
{'Avi': [90], 'Moshe': [80, 100], 'Adam': [70]}
{'Avi': [90], 'Moshe': [80, 100], 'Adam': [70], 'Johnny': [60]}
כפי שניתן לראות, שני המילונים מכילים את הציון 100 ברשימת ציוניו של משה.
זאת מכיוון ששכפול המילון לא שכפל את הרשימה בזכרון אלא רק הפנה אליה מ2 המילונים - המקורי והמשוכפל.
עצרו וחשבו: האם המילון המקורי היה משתנה גם הוא עבור הפעולה stud_2[‘Moshe’]=[100]?
פעולה זו מבצעת השמה של רשימה חדשה למפתח משה, ולא מעדכנת את הערך הקיים. לכן, מה שמשתנה הוא הערכים אליהם מצביעים מפתחות המילון ולא הערכים המקוריים בעצמם. לכן, המילון המקורי (stud) לא יתעדכן במקרה זה.
עדכון מילון d.update(d_other)
מתודה זו מקבלת מילון (d_other), ומבצעת השמה במילון d של כל זוג מפתח-ערך של במילון d_other. כלומר, עבור כל זוג מפתח-ערך בd_other:
אם מפתח לא קיים ב
d, הוא מתווסף למילון.אם המפתח כבר קיים ב
d, הערך שלו נדרס ומעודכן להיות לערך שמופיע בd_other.
בדרך זו, ניתן לעדכן מילונים בלי לבצע השמה בלולאה עבור כל אחד מהזוגות מפתח-ערך המופיעים במילון d_other.
בדוגמא הבאה, המילון studs_2 ישמש כארגומנט על מנת לעדכן את המילון studs:
studs = {"Avi": 90, "Moshe": 80, "Adam": 70}
studs_2 = {"Moshe": 100, "Johnny": 60}
studs.update(studs_2)
print(studs)
{'Avi': 90, 'Moshe': 100, 'Adam': 70, 'Johnny': 60}
נשים לב לנקודות הבאות בקוד לעיל:
ציונו של משה בstuds עודכן מכיוון שהופיע גם ב
studs_2ציונו של ג’וני התווסף ל
studsמכיוון שהופיע גםstuds_2ולא הופיע בstudsבדומה למתודות כמו
appendוremoveברשימות, גם כאן העדכון נעשה ישירות על גבי אובייקט המילון המקורי (in-place), ולא על גבי עותק של האובייקט המקורי.
הוצאה ממילון d.pop(k)
המתודה pop פעולת מזכירה את אותה מתודת pop שנתקלנו בה כבר ברשימות, רק במקום אינדקסים אנחנו עובדים עם מפתחות. כלומר, אנחנו יכולים לבחור מפתח מסוים במילון, להוציא אותו ולקבל את הערך שלו.
אם ננסה לבצע pop על מפתח לא קיים, נקבל שגיאה.
נבחן את הדוגמא הבאה:
studs = {"Avi": 90, "Moshe": 80, "Adam": 70}
print(studs.pop("Moshe"))
print(studs)
80
{'Avi': 90, 'Adam': 70}
בדוגמא זו, ערך ההחזר של המתודה studs.pop("Moshe") הוא 80, שזהו ציונו של משה.
לאחר ביצוע הפעולה, הוסר מהמילון המפתח (והערך) המייצג את הסטודנט משה.
כפי שאמרנו, הסרת מפתח שאינו קיים מהמילון תוביל לשגיאה, ולכן אם ננסה להסיר שוב את משה נקבל את השגיאה הבאה:
studs.pop("Moshe")
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
Cell In[35], line 1
----> 1 studs.pop("Moshe")
KeyError: 'Moshe'
כלומר, המפתח "Moshe" אינו קיים במילון.
סיכום מתודות מילונים#
פונקציה |
תיאור |
|---|---|
|
יוצר מילון ריק |
|
קובע את הערך של |
|
מחזיר |
|
מחזיר את הערך של המפתח |
|
מחזיר תצוגה של כל המפתחות במילון |
|
מחזיר תצוגה של כל הערכים במילון |
|
מחזיר תצוגה של זוגות |
|
מחזיר את |
|
מסיר את המפתח |
|
יוצר העתק רדוד של המילון (המילון בלבד מועתק, לא האובייקטים שבתוכו) |
|
מוסיף את כל הפריטים מהמילון |
ארגומנט שמסומן כ־[d] הוא אופציונלי
אם לא מציינים אותו, ייעשה שימוש בערך ברירת המחדל
מידע נוסף על מתודות של מילון נמצא כאן
דוגמא מסכמת: מונה תדירות תווים#
בדוגמה זו נתרגל את המתודות שלמדנו על שימוש מעניין של מילון.
ממשו את הפונקציה get_char_count אשר מקבלת מחרוזת, ומחזירה מילון המקשר בין אות לכמות ההופעות שלה במחרוזת.
def get_char_count(st):
# Write your code here
pass
רמז
נחלק את התרגיל למספר שלבים:
נתחיל בליצור מילון ריק, אליו נכניס את כל הספירה.
נרצה לעבור על כל תו במחרוזת כדי לספור אותו.
אם התו לא קיים במילון, זו הפעם הראשונה שהוא מופיע במחרוזת. נוסיף אותו למילון עם ערך התחלתי של 1.
אם התו כבר קיים במילון, הוא כבר הופיע במחרוזת בעבר, ונרצה להוסיף 1 לערך שכבר היה קיים לו במילון.
לאחר שסיימתם לממש את הקוד, בדקו את נכונותו בהרצות הבאות:
text = 'jerry'
get_char_count(text)
text = 'supercalifragilisticexpialidocious'
get_char_count(text)
לחצו כאן כדי לצפות בפתרון
def get_char_count(text):
char_count = {}
for char in text:
if not char in char_count:
char_count[char] = 1
else:
char_count[char] += 1
return char_count
מונה תדירות תווים משופר#
נסו לממש את כל תוכן הפונקציה ב4 שורות קוד בלבד.
רמז
על-ידי שימוש נכון במתודה get, ניתן לממש את כל תוכן הפונקציה ב4 שורות קוד בלבד.
def get_char_count(text):
# Write your code here
רמז
עד כה ביצענו לכל תו במחרוזת: אם התו במילון - תוסיף לו 1. אם התו לא במילון - תכניס אותו מחדש עם הערך 1.
נסו לשחק עם הערך הדיפולטי שget מחזירה, כך שניתן יהיה לבצע את אותה פעולה על מפתח שכבר היה קיים, ומפתח חדש לחלוטין.
תזכורת: יצירת איבר חדש נראית זהה לדריסה של ערך באיבר קיים.
לאחר שסיימתם לממש את הקוד, בדקו את נכונותו בהרצות הבאות:
text = 'jerry'
get_char_count(text)
text = 'supercalifragilisticexpialidocious'
get_char_count(text)
לחצו כאן כדי לצפות בפתרון
def get_char_count(text):
char_count={}
for char in text:
char_count[char] = char_count.get(char, 0) + 1
return char_count
מה בעצם קורה פה?
עד כה ביצענו לכל תו במחרוזת: אם התו במילון - תוסיף לו 1. אם התו לא במילון - תכניס אותו מחדש עם הערך 1.
במקום זאת, אנחנו מחליפים את הכל בפקודת get אחת!
אם התו היה במילון - הפקודה תחזיר את הערך שהיה לו, תוסיף לו 1, ותשמור אותו חזרה באותו המפתח.
אם התו לא היה במילון - הפקודה תחזיר 0, תוסיף לו 1, ותשמור אותו (לראשונה) במילון תחת המפתח המתאים.
מונה תדירות תווים: הדפסת תוצאה ממוינת#
עכשיו כשיש לנו פונקציה עובדת, היינו רוצים להדפיס את המונה התווים שלנו בסדר הגיוני. באיזה סדר נרצה להדפיס את התוצאה?
אפשרות ראשונה - לפי סדר אלפביתי: תחילה את מספר המופעים של a, לאחר מכן את מספר המופעים של b וכו’.
במקרה זה אנחנו רוצים שהמילון יודפס כך שהמפתחות יהיו מסודרים.
ניתן לבצע זאת על ידי הפונקציה sorted, שבברירת המחדל שלה ממיינת את המפתחות, לפי סדר אלפביתי.
def print_by_keys_order(d):
sorted_chars = sorted(d)
for char in sorted_chars:
print(char, ':', d[char])
text = 'supercalifragilisticexpialidocious'
cc = get_char_count(text)
print_by_keys_order(cc)
אפשרות שניה - לפי תדירות: להתחיל מהאות שמופיעה הכי הרבה פעמים ולסיים בזו שמופיעה הכי מעט.
הפעם אנחנו דווקא רוצים לסדר את המילון לפי הערכים, כלומר לפי מה שהמתודה get מחזירה לנו. גם לשם כך נשתמש בsorted, אך הפעם נוסיף לה שני פרמטרים נוספים:
key- ראינו במודול פונקציות שניתן לתת לkeyפונקציה לפיה לסדר את המילון. תזכורת: אין סוגריים לgetמאחר שמדובר בשם הפונקציה ולא בקריאה לה.reverse- אנחנו אומרים לפונקציהsortedלסדר מהגדול לקטן, במקום מהקטן לגדול.
def print_by_keys_order(d):
sorted_chars = sorted(d, key=d.get, reverse=True)
for char in sorted_chars:
print(char, ':', d[char])
text = 'supercalifragilisticexpialidocious'
cc = get_char_count(text)
print_by_keys_order(cc)