המתודות flat ו-flatMap ב-JavaScript

בפוסט זה אסביר על המתודות flat ו-flatMap ב-JavaScript, מתודות די ותיקות אבל כאלו שחבל מאוד שלא להכיר.

המתודות flat ו-flatMap הינן מתודות די ותיקות (ECMA 2019) אבל אני חושב שבאופן די מזור, לא כולם מכירים אותן וחבל, כי באמת שהן מעולות.

Array.flat()

Array.flat מאפשר "לשטח" מערכים המכילים מערכים בתוכם.
כן, ישנן לא מעט דרכים, למשל, באמצעות concat:

let myArr = [4,6,7,[3,9,12]];
let myNewArr = [].concat.apply([], myArr); // [4, 6, 7, 3, 9, 12]

או באמצעות concat ו-spread:

let myArr = [4,6,7,[3,9,12]];
let myNewArr = [].concat(...myArr); // [4, 6, 7, 3, 9, 12]

אבל אם יש לנו יותר מ-2 רמות, כמו המערך הבא למשל, זה יהיה כבר קצת יותר מסובך:

let myArr = [4,6,7,[3,[9,12]]];
let myNewArr = [].concat(...myArr); // [4, 6, 7, 3, Array(2)]

ואיך זה מתבצע באמצעות flat? קליל ופשוט:

let myArr = [4,6,7,[3,9,12]];
let myNewArr = myArr.flat(); // [4, 6, 7, 3, 9, 12]

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

אוכל לפשט אותו ב-2 רמות באופן הבא:

let myArr = [4,6,7,[3,[9,12]]];
let myNewArr = myArr.flat().flat(); // [4, 6, 7, 3, 9, 12]

או באופן הפשוט יותר, לציין כארגומנט את מספר הרמות שיש במערך:

let myArr = [4,6,7,[3,[9,12]]];
let myNewArr = myArr.flat(2); // [4, 6, 7, 3, 9, 12]

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

let myArr = [4,6,7,[3,[9,12]]];
let myNewArr = myArr.flat(Infinity); // [4, 6, 7, 3, 9, 12]

השמטת איברים ריקים במערך

חשוב לדעת שהמתודה flat משמיטה איברים ריקים במערך, אם קיימים כאלו:

let myArr = [4,6,,[3,,12]];
let myNewArr = myArr.flat(Infinity); // [4, 6, 3, 12]

Array.flatMap()

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

let myArr = [4, 6, 7, 3, 9, 12];
let myNewArr = myArr.map(x => [x * 2]); // [[8],[12],[14],[6],[18],[24]]

אז יש פתרון, באמצעות reduce ו-concat:

let myArr = [4, 6, 7, 3, 9, 12];
let myNewArr = myArr.reduce((accumulator, x) => accumulator.concat([x * 2]), []); // [8, 12, 14, 6, 18, 24]

תכל'ס קצת מבולגן, לא?
בדיוק בשביל זה יש לנו את flatMap שתחזיר מערך אחד שמכיל את כל התוצאות:

let myArr = [4, 6, 7, 3, 9, 12];
let myNewArr = myArr.flatMap(x => [x * 2]); //[8, 12, 14, 6, 18, 24]

אבל מה שכן, צריך לדעת ש-flatMap משטחת רק רמה אחת:

let myArr = [4, 6, 7, 3, 9, 12];
let myNewArr = myArr.flatMap(x => [[x * 2]]);  // [[8],[12],[14],[6],[18],[24]]

שינוי של איברים במערך באמצעות flatMap

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

let myArr = [42, 33, 15, 77, 45, 68, 88, 19, 50, 92];
myArr.flatMap((item) =>
  (item < 60) ? [] : [item]); // [77, 68, 88, 92]

או למשל להפוך כל מספר שקטן מ-60 ל-60:

let myArr = [42, 33, 15, 77, 45, 68, 88, 19, 50, 92];
let myNewArr = myArr.flatMap((item) =>
  (item < 60) ? [60] : [item]);

וכמובן שיש עוד המון שימושים מעניינים.

סיכום

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

בהצלחה!

נהנת ממאמר זה? הירשם לרשימת התפוצה וקבל עדכונים על מאמרים חדשים!


רק רגע! :)
כשאני לא כותב פוסטים ב-CodeBrain אני מספק שרותי פיתוח, ייעוץ והדרכה.
אם נראה לך שאני האיש המתאים עבורך, כדאי שנדבר :)

3 תגובות בנושא “המתודות flat ו-flatMap ב-JavaScript”

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

    1. נכון איתמר, אתה בהחלט צודק, אבל הרעיון בדוגמה היה להראות את השימוש ב-flatMap.

כתיבת תגובה

האימייל לא יוצג באתר.