המדריך האולטימטיבי לפונקציית המפה של פייתון לעיבוד נתונים

מבוא

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

התחביר של פונקציית map() הוא כדלקמן:

map(function, iterable, [iterable 2, iterable 3, ...])

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

במדריך זה, נסקור שלוש דרכים שונות לעבודה עם map(): עם פונקציית lambda, עם פונקציה שהוגדרה על ידי המשתמש, ולבסוף עם פונקציה מובנית המשתמשת בנתוני iterable מרובים.

שימוש בפונקציית Lambda

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

תחביר של map() עם פונקציית lambda הוא כדלקמן:

map(lambda item: item[] expression, iterable)

עם רשימה כמו זו הבאה, אנו יכולים לממש פונקציית lambda עם ביטוי שאותו אנו רוצים ליישם על כל פריט ברשימה שלנו:

numbers = [10, 15, 21, 33, 42, 55]

כדי ליישם ביטוי על כל אחד מהמספרים שלנו, אנו יכולים להשתמש בmap() ובlambda:

mapped_numbers = list(map(lambda x: x * 2 + 3, numbers))

כאן אנו מכריזים על פריט ברשימה שלנו כx. ואז אנו מוסיפים את הביטוי שלנו. אנו מעבירים את רשימת המספרים שלנו כ-iterable עבור map().

על מנת לקבל את התוצאות מיד, אנו מדפיסים רשימה של אובייקט הmap:

print(mapped_numbers)
Output
[23, 33, 45, 69, 87, 113]

השתמשנו ב-list() כך שהאובייקט של המפה מוחזר לנו כרשימה, ולא כאובייקט פחות קריא כמו: <map object at 0x7fc250003a58>. האובייקט של המפה הוא איטרייטור על התוצאות שלנו, כך שנוכל לעבור עליו עם for או שנוכל להשתמש ב-list() כדי להפוך אותו לרשימה. אנחנו עושים זאת כאן כי זו דרך טובה לעבור על התוצאות.

בסופו של דבר map() הכי שימושי כשעובדים עם מערכות נתונים גדולות, אז ככל הנראה נמשיך לעבוד עם האובייקט של המפה, ובדרך כלל לא נשתמש בבנאי כמו list() עליהם.

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

יישום פונקציה שהוגדרה על ידי המשתמש

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

לדוגמה, באיטרביל הבא, כל פריט הוא מילון שמכיל פרטים שונים על כל אחד מהיצורים באקווריום שלנו:

aquarium_creatures = [
 {"name": "sammy", "species": "shark", "tank number": 11, "type": "fish"},
 {"name": "ashley", "species": "crab", "tank number": 25, "type": "shellfish"},
 {"name": "jo", "species": "guppy", "tank number": 18, "type": "fish"},
 {"name": "jackie", "species": "lobster", "tank number": 21, "type": "shellfish"},
 {"name": "charlie", "species": "clownfish", "tank number": 12, "type": "fish"},
 {"name": "olly", "species": "green turtle", "tank number": 34, "type": "turtle"}
]

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

def assign_to_tank(aquarium_creatures, new_tank_number):
 def apply(x):
  x["tank number"] = new_tank_number
  return x
 return map(apply, aquarium_creatures)

אנחנו מגדירים פונקציית assign_to_tank() שלוקחת את aquarium_creatures ואת new_tank_number בפרמטרים. בפונקציית assign_to_tank() אנחנו מעבירים את apply() כפונקציה לmap() בשורה האחרונה. פונקציית assign_to_tank תחזיר את האיטרטור الناتج מmap().

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

לאחר מכן אנחנו מגדירים שx הוא המפתח "tank number" מaquarium_creatures ושזה צריך לאחסן את new_tank_number שהועבר. אנחנו מחזירים כל פריט לאחר החלת מספר הטנק החדש.

אנחנו קוראים לassign_to_tank() עם רשימת המילונים שלנו ומספר הטנק החדש שאנחנו רוצים להחליף עבור כל יצור:

assigned_tanks = assign_to_tank(aquarium_creatures, 42)

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

print(list(assigned_tanks))

נקבל את הפלט הבא מהתוכנית הזו:

Output
[{'name': 'sammy', 'species': 'shark', 'tank number': 42, 'type': 'fish'}, {'name': 'ashley', 'species': 'crab', 'tank number': 42, 'type': 'shellfish'}, {'name': 'jo', 'species': 'guppy', 'tank number': 42, 'type': 'fish'}, {'name': 'jackie', 'species': 'lobster', 'tank number': 42, 'type': 'shellfish'}, {'name': 'charlie', 'species': 'clownfish', 'tank number': 42, 'type': 'fish'}, {'name': 'olly', 'species': 'green turtle', 'tank number': 42, 'type': 'turtle'}]

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

שימוש בפונקציה מובנית עם מספר איטרטורים

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

כאן יש לנו את הרשימות של המספרים השלם שאנו רוצים להשתמש בהם עם pow():

base_numbers = [2, 4, 6, 8, 10]
powers = [1, 2, 3, 4, 5]

לאחר מכן אנו מעבירים את pow() כפונקציה שלנו לmap() ומספקים את שתי הרשימות כאיטרטורים שלנו:

numbers_powers = list(map(pow, base_numbers, powers))

print(numbers_powers)

map() יחיל את הפונקציה pow() על אותו פריט בכל רשימה כדי לספק את החזקה. לכן התוצאות שלנו יראו 2**1, 4**2, 6**3, וכן הלאה:

Output
[2, 16, 216, 4096, 100000]

אם היינו מספקים לmap() איטרטור שהיה ארוך יותר מהאחר, map() היה מפסיק לחשב ברגע שהוא מגיע לסוף האיטרטור הקצר יותר. בתוכנית הבאה אנו מרחיבים את base_numbers עם שלושה מספרים נוספים:

base_numbers = [2, 4, 6, 8, 10, 12, 14, 16]
powers = [1, 2, 3, 4, 5]

numbers_powers = list(map(pow, base_numbers, powers))

print(numbers_powers)

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

Output
[2, 16, 216, 4096, 100000]

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

סיכום

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

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

כדי להעמיק את ההבנה שלך של פייתון, אנא השתמש במשאבים הבאים:

משאבים אלה יספקו לך הבנה מקיפה של היכולות של Python ואיך להשתמש בהם ביעילות בפרויקטים שלך.

אם תרצה ללמוד עוד על Python, בדוק את סדרת איך לקודד ב-Python ואת דף הנושא של Python. כדי ללמוד יותר על עבודה עם סטי נתונים בתכנות פונקציונלי, עיין במאמר שלנו על פונקציית filter().

שאלות נפוצות

מה עושה map() ב-Python?

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

numbers = [1, 2, 3, 4]
squares = map(lambda x: x**2, numbers)

כאן, squares יהיה מאפיין של 1, 4, 9, 16.

איך יוצרים מפה בפייתון?

יוצרים אובייקט מיפוי על ידי קריאה לפונקציה המובנית map() עם פונקציה ולפחות איבר אחד כארגומנטים. לדוגמה:

def add_one(x):
    return x + 1

my_list = [1, 2, 3]
mapped = map(add_one, my_list)  # יוצר אובייקט מיפוי

ניתן לאחר מכן לעבור על המיפוי או להמיר אותו לרשימה כדי לראות את התוצאות:

print(list(mapped))  # [2, 3, 4]

האם המפה עצלנית בפייתון?

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

איך פועלת הפונקציה map()?

הפונקציה map() פועלת כך:

  1. אתה מספק פונקציה ואחד או יותר מאגרים.
  2. map() שולפת אלמנט מכל מאגר.
  3. היא קוראת לפונקציה עם האלמנטים הללו כארגומנטים.
  4. היא מחזירה את התוצאה של קריאת הפונקציה הזו.
  5. התהליך הזה חוזר על עצמו עד שאחד מהמאגרים מסתיים.

אם ניתנים מספר מאגרים, map() מפסיקה כאשר המאגר הקצר ביותר מתמלא. לדוגמה:

numbers = [1, 2, 3]
others = [10, 20, 30]
result = map(lambda x, y: x + y, numbers, others)
print(list(result))  # [11, 22, 33]

האם עליי להשתמש בmap בפייתון?

אם עליך להשתמש בmap() תלוי בהעדפה האישית ובקריאות:

יתרונות:

  • זה יכול להיות תמציתי יותר בחלק מהמקרים.
  • זה יכול להיות מעט מהיר יותר מאגרים של רשימות במקרים מסוימים (אם כי לעיתים קרובות לא בצורה משמעותית).

חסרונות:

  • קוד שמשתמש באגרים של רשימות או בביטויי גנרטורים נחשב לעיתים קרובות ליותר "פייתוני" ולקריא יותר.
  • מפתחים חדשים בפייתון עשויים למצוא את הבנת רשימות קומפקטיות יותר אינטואיטיבית.

בקצרה, השתמש ב-map() אם זה עושה את הקוד שלך ברור וישיר יותר. אחרת, הבנות רשימות או ביטויי גנרטור הם חלופה מאוד נפוצה.

איך להמיר map למחרוזת בפייתון?

אובייקט map הוא מאיטרטור, לא מחרוזת. אם אתה רוצה להמיר את התוצאות של קריאה ל-map() למחרוזת, קודם כל אתה צריך לאתחל עליו. גישות נפוצות כוללות:

  • המרה לרשימה ולאחר מכן לייצוג מחרוזת:
mapped = map(str, [1, 2, 3])
string_representation = str(list(mapped))  # "[‘1’, ‘2’, ‘3’]"
  • חיבור התוצאות אם הן אלמנטים מחרוזת:
mapped = map(str, [1, 2, 3])
joined_string = ''.join(mapped)  # "123"

השיטה הטובה ביותר תלויה אם אתה רוצה ייצוג רשימה קריא לאדם (str(list(...))) או חיבור של התוצאות (''.join(...)).

מה עושה map count()?

אובייקטי map ב-Python אינם כוללים מתודת count() מובנית. מתודת count() זמינה על רשימות, מיתרים ואוספים מסוימים אחרים. אם אתה רוצה לספור את ההתרחשויות של ערך המיוצר על ידי אובייקט map, עליך קודם לכן להמיר אותו לרשימה (שצורכת את המאסף):

mapped = map(lambda x: x*2, [1, 2, 3, 2])
mapped_list = list(mapped)
count_of_4 = mapped_list.count(4)  # 2, כי 2*2=4 מופיע פעמיים

אם אתה זקוק לספירה מבלי להמיר לרשימה, תוכל לחזור ידנית:

count_of_value = sum(1 for x in map(lambda x: x*2, [1, 2, 3, 2]) if x == 4)

מה עושים map וfilter ב-Python?

  • map(function, iterable): מפעיל פונקציה על כל אלמנט של iterable ומחזיר מאסף של התוצאות.

  • filter(function, iterable): מחזיר מאסף של אלמנטים מ-iterable עבורם function(element) הוא True. אם הפונקציה היא None, היא מחזירה אלמנטים שהם אמיתיים בעצמם.

לדוגמה:

nums = [1, 2, 3, 4, 5]
mapped_nums = map(lambda x: x*2, nums)        # [2, 4, 6, 8, 10]
filtered_nums = filter(lambda x: x > 2, nums) # [3, 4, 5]

map ממיר כל אלמנט, בעוד שfilter בוחר אלמנטים מסוימים בהתבסס על תנאי.

Source:
https://www.digitalocean.com/community/tutorials/how-to-use-the-python-map-function