תחי ישראל - אין לנו ארץ אחרת

תחי ישראל -אין לנו ארץ אחרת

Reduce - האולר השווייצרי של טיפול במערכים של JavaScript

מחבר:
בתאריך:

הפונקציה reduce של JavaScript

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

  • foreach שהיא דרך אלגנטית לכתוב לולאה של JavaScript.
  • סינון מערכים ב JavaScript-באמצעות הפונקציה filter
  • טרנספורמציה של מערכים ב-JavaScript באמצעות הפונקציה map
  • sort מאפשר לנו לסדר מערך לפי סדר. לדוגמה, לסדר פריטים של מערך מספרים מערך גבוה לנמוך. או הפוך.

 

הפונקציה reduce של JavaScript

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

יהיה יותר פשוט אם נלמד באמצעות דוגמאות מועילות:

 

סכום של מערך מספרים באמצעות reduce

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

הפונקציה reduce מקבלת שני פרמטרים:

  • פונקציה שמבצעת פעולה על כל פריט של המערך.
    פונקציה זו מקבלת 2 ערכים:
    1. צובר (total) שבו מצטברים הערכים שמתווספים בכל פעם שהלולאה רצה
    2. הפריט הנוכחי (item)
  • ערך התחלתי - הפונקציה מתחילה לצבור מערך שאותו אנחנו צריכים להגדיר מראש.
let numbers = [9, 41, 6, 78];
let res = numbers.reduce(function(total, item) {
    return total + item
}, 0);
console.log(res); // 134

בדוגמה שלנו, אנחנו רוצים לסכום את המספרים שנמצאים במערך המספרים numbers כדי לקבל את הסה"כ. לשם כך, reduce עוברת על כל אחד מפריטי המערך בלולאה, ועבור כל פריט קוראת לפונקציה אנונימית שמחזירה את הערך הצבור (total) בתוספת הפריט הנוכחי. ה-total מתחיל מ-0, ובכל פעם שהלולאה רצה מתווסף הערך התורן עד שמצטבר הסה"כ.

ואפשר לכתוב את אותה הפונקציה באופן אלגנטי יותר באמצעות תחביר fat arrow של ES6:

let res   = numbers.reduce((total, item) => {return total + item}, 0);

שני דברים שכדאי לשים אליהם לב:

  1. הפונקציה האנונימית צריכה להחזיר ערך אז תמיד להקפיד שיהיה return.
  2. להוסיף את הערך ההתחלתי שממנו מתחילה הפונקציה לצבור את הסה"כ. במקרה זה השתמשנו ב-0. אם לא נקפיד על על שימוש בערך התחלתי, הפונקציה תנסה למצוא ערך כזה, ואז לא בטוח שנקבל את התוצאה הרצויה.

כפי שניתן לסכום מערך של מספרים, ניתן למצות סכום של מספרים מתוך מערך שבו כל פריט מכיל מספר שדות.

בדוגמה הבאה, אנחנו מעוניינים למצוא את השווי של צי מכוניות.

let cars = [
  {
    name  : 'Toyota',
    price : 140000,
    number: 3
  },
  {
    name  : 'BMW',
    price : 190000,
    number: 6
  },
  {
    name  : 'Sussita',
    price : 4000,
    number: 1
  }
];

let res = cars.reduce( (total, item) => {
  return total + item.price * item.number;
}, 0);

console.log(res); // 1564000

בכל פעם שהלולאה רצה, מוכפל מספר המכוניות מכל סוג במחיר, ואז מתווסף ל-total, שמתחיל מ-0.

ואפשר להיות קצת יותר מתוחכמים ולסכום את הפריטים שאינם סוסיתא.

let res = cars.reduce( (total, item) => {
  return item.name !== 'Sussita'? total + item.price * item.number : total;
}, 0);

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

 

מציאת מספר הפריטים מכל סוג באמצעות reduce

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

// Creating a tally with reduce
let cars = ['Honda', 'Toyota', 'Sussita', 'Tesla', 'BMW', 'Toyota', 'Honda', 'Mitsubishi'];
let res = cars.reduce( (total, item) => {
  total[item] = (total[item] || 0) + 1 ;
  return total;
} , {});
console.log(res); // {BMW:1, Honda:2, Mitsubishi:1, Sussita:1, Tesla:1, Toyota:2}

במידה והפריט אינו קיים הוא יקבל את הערך 0, ואם הפריט כבר קיים יתווסף לערך 1.

 

שיטוח מערך רב ממדי באמצעות reduce

בדוגמה הבאה, נשתמש ב-reduce כדי לשטח מערך רב-ממדי, ולהפוך אותו למערך בממד אחד.

// Flattening an array of arrays with reduce
let letters = [['a', 'b', 'c'], ['o','e','i']];
let res = letters.reduce((total, item) => {
  return total.concat(item);
}, []); // ["a", "b", "c", "o", "e", "i"]
console.log(res);

בכל פעם שהלולאה רצה, מתווסף הפריט התורן למערך res.

 

הרצת מספר פונקציות שמכונסות ביחד במערך כדי לקבל את התוצאה הרצויה

ב-JavaScript פונקציות הם ערכים, ולכן אפשר לכנס פונקציות לתוך מערך.

פונקציות הם ערכים בגלל שאפשר לכתוב כך:

let split = (input) => input.split("");

וערכים ניתן לשלב לתוך מערך.

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

let split       = (input) => input.split("");
let reverse = (input) => input.reverse();
let join       = (input) => input.join("");

let pipeline = [split, reverse, join];
let result   = pipeline.reduce((total, item) => {return item(total)}, "000,1");
console.log(result); // 1,000

3 הפונקציות שישמשו אותנו לביצוע המשימה הם:

  • split שעם הפרמטר של מחרוזות ריקה מפרק מחרוזת למערך.
  • reverse שהופך את כיוונו של המערך (פריט ראשון הופך לאחרון).
  • הפונקציה join שמצרפת מערך למחרוזת.

את שלושת הפונקציות כינסנו למערך ששמו pipeline

השתמשנו ב-reduce כדי להפעיל את הפונקציות במערך לפי סדר, במטרה להפוך את המחרוזת "000,1" ל-"1,000".

 

צירוף פונקציות

היופי בפונקציות שאנחנו לומדים שניתן לצרף אותם אחת לשנייה, ולהשיג הרבה מאוד בקוד מאוד קצר.

לדוגמה, הקוד הבא שבאמצעותו נחשב את הערך הכולל של המכוניות בש"ח בתנאי שמחיר המכונית גבוה מ-4000.

let sum = cars
  .filter((item) => (item.price > 40000))
  .map((item)    => item.price * 3.5)
  .reduce((total, item) => {return total + item}, 0);

נסביר מה עשינו:

  • קודם כל, סיננו את הפריטים שמחירם גבוה מ-400 באמצעות filter
  • ואח"כ כפלנו ב-3.5, וקיבלנו את המחיר בשקלים באמצעות הפונקציה map
  • ובסוף השתמשנו ב-reduce כדי לקבל את הסה"כ

מדריכי JavaScript למתקדמים

 

אהבתם? לא אהבתם? דרגו!

0 הצבעות, ממוצע 0 מתוך 5 כוכבים

 

 

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

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

שימו לב! הסקריפטים במדריכים מיועדים למטרות לימוד בלבד. כשאתם עובדים על הפרויקטים שלכם אתם צריכים להשתמש בספריות וסביבות פיתוח מוכחות, מהירות ובטוחות.

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

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

הוסף תגובה חדשה

 

 

ענה על השאלה הפשוטה הבאה כתנאי להוספת תגובה:

מתי הוקמה המדינה?

 

תמונת המגיב

רוברט בתאריך: 31.03.2018

דוגמה מצוינת. תודה רבה.

תמונת המגיב

מיכל בתאריך: 03.11.2021

היי אני אוהבת מאוד את ההסברים שלך. אני קצת התקשתי להבין ואשמח לדעת ב מציאת מספר הפריטים מכל סוג באמצעות כתבת את השורה הזו -total[item] = (total[item] || 0) + 1 ; מה זה בסוגריים ? מה היא עושה מה היא אומרת

תמונת המגיב

יוסי בן הרוש בתאריך: 03.11.2021

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

תמונת המגיב

זלמן בתאריך: 08.02.2023

ממש מוצלח ניסיתי להבין במקומות אחרים וממש לא הצלחתי להבין מסביר ממש טוב! תודה רבה