מילונים חלק ד' – פעולות נוספות

ברוכים הגולשים לחלק הרביעי, והאחרון (אני מבטיח), על מילונים. בפוסט אציג כמה פעולות שכנראה יהיו שימושיות עבורכם כאשר תתחילו להתעסק עם מילונים בקוד שלכם.

מיזוג מילונים

הרעיון פשוט, יש לנו מידע מסוים במילון הזה, מידע אחר במילון ההוא – ואנחנו רוצים הכל במילון אחד.
המתודה update עושה בדיוק את זה.
לצורך הדוגמה אצור שני מילונים שמכילים שמות של צוותים מפורסמים (מפתח) ומספר החברים בהן (ערך)

אולי הנתונים האלה הגיעו ממקורות שונים אבל אני לא באמת זקוק לשני מילונים נפרדים. כדי לאחד אותם נקרא ל-update ממילון אחד וניתן לה כפרמטר את המילון השני.

update תעדכן את המילון הראשון (super_groups) בצורה הבאה: כל מפתח חדש במילון השני יתווסף לראשון וכל מפתח קיים יעודכן לערך שמצויין במילון השני.

אפשר לראות שהמילון השתנה ועכשיו הוא מכיל את כל הצמדים מהמילון השני. הנוקמים גדלו מ-6 (המספר המקורי שלהם מ-2012) ל-10 (מספרם בעידן אולטרון" מ-2015)

מה אם נרצה לאחד אותם לתוך משתנה חדש, תוך שמירה על הרשימות המקוריות? בשביל זה נוכל להשתמש בסינטקס הבא (הצורה הזאת קיימת החל מפייתון 3.5 ומעלה בלבד):

יתרון נוסף בצורה הזו היא שאנו לא מוגבלים לשני מילונים בלבד, אלא יכולים לאחד כמה מילונים שנרצה בצורה כזאת:

ערכים כפולים יעודכנו ע"פ סדר הופעת המילונים, משמאל לימין.

מיון מילונים

בדומה לסטים, אי אפשר באמת למיין אובייקט מסוג מילון – הערכים שבו אינם מסודרים בסדר מסויים – אבל אפשר להציג את המידע שנמצא בו בצורה ממויינת. מהסיבה הזאת אין למילונים את המתודה sort שיש לרשימות, למשל.

מיון לפי מפתחות

אמנם אין sort אבל נוכל להשתמש בפונקציה sorted כדי להחזיר רשימה ממוינת של המפתחות במילון.
בואו נראה איך הפונקציה sorted תעבוד על המילון הזה, המכיל את שמות 10 הסרטים הכי רווחיים בהיסטוריה והרווחים שלהם בכל העולם, במיליארדי דולרים (הנתונים ע"פ Box Office Mojo, נכון לספטמבר 2018):

אפשר לראות שהפונקציה מחזירה לנו רשימה של שמות הסרטים, מסודרים בסדר אלפביתי. המילון המקורי נותר ללא שינוי כמובן.
נוכל להשתמש בפרמטר reversed כדי להפוך את סדר המיון

השיטה הזאת עובדת אבל ע"י פירוק של המילון לרשימה אנחנו מקבלים רק חלק מהמידע, רווחי הסרטים חסרים.
אפשר להשתמש ברצף השמות הממוין כדי לשלוף את המספרים הרלוונטיים מהמילון

זה כבר יותר טוב אבל הסרטים האלה נמצאים במילון הזה בזכות כמות הכסף שהם הכניסו, לא השם שלהם. לכן כנראה שיהיה יותר שימושי למיין אותם ע"פ הרווח, כלומר למיין את המילון על פי הערכים ולא המפתחות

מיון לפי ערכים

מיון מילון לפי ערכים הוא כבר קצת יותר "טריקי" כי כשאנחנו ממיינים מילון הוא ימוין על פי המפתחות. אנחנו יכולים לקבל את הערכים ממוינים על ידי שימוש במתודה values אבל ממש כמו המיון של המילון, נקבל כאן רשימה שמכילה רק חלק מהנתונים במילון. במקרה הזה מדובר בנתוני הרווחים וללא שמות הסרטים הרשימה הזאת לא מעניינת במיוחד.

דרך אחת להשיג את מה שאנחנו רוצים היא ע"י שימוש במתודה items שמארגנת לנו את נתוני המילון ברשימת צמדים, ובפונקציה itemgetter ממודול שנקרא operator. די מורכב להסביר מה הפונקציה הזאת עושה ולכן לא אכנס לזה כאן. מספיק להבין שעל ידי שימוש בה אנחנו יכולים להגדיר לפונקציית המיון sorted את הערכים (רווחים) כמפתח למיון, במקום המפתחות (שמות הסרטים).
כדי להציג את הסרט הרווחי ביותר בהתחלה אשתמש ב-reversed שתציג את הסרטים ע"פ הרווחים בסדר יורד.

דרך קצת יותר פשוטה ואלגנטית תהיה להשתמש בביטוי lambda. ביטוי lambda הוא, בפשטות, הגדרת פונקציה במשפט קצר אחד אבל לביטויים האלה אקדיש פוסט שלם בהמשך אז אל תדאגו אם אתם לא מבינים את הקוד הזה כרגע.

העתקת מילונים

כמו סטים או רשימות, גם מילונים אפשר לשכפל באמצעות המתודה copy ובכך לייצר עותק חדש של האובייקט שאותו ניתן לשנות – מבלי להשפיע על המקור (מה שלא יקרה אם יהיו לנו משתנים רבים המצביעים לאותו המילון)

הסיבה שהמתודה הזאת נחוצה היא, כמו שהסברתי בפוסטים קודמים, הצורה שבה פייתון מנהלת את האובייקטים שאנו מגדירים בזיכרון. "הצבה" של אובייקט היא בעצם הצבעה אליו וכמה משתנים ה"מכילים" את אותו המילון בעצם מצביעים אל אובייקט יחיד בזיכרון. לכן גם אם נציב מילון במשתנה dict1 ואז נשווה את משתנה dict2 אליו, שניהם מצביעים אל אותו האובייקט ושינוי על אחד מהם יחול גם על השני. על ידי שימוש במתודה copy כל שינוי שנבצע על אחד משני המילונים האלה לא ישפיע על המילון השני, הם עותקים נפרדים לגמרי.