Farzaneh Parvar
Farzaneh Parvar
خواندن ۶ دقیقه·۵ سال پیش

متدهای map و filter در جاوااسکریپت

به عنوان دولوپر جاوااسکریپت همیشه با لیست ها و آرایه ها سروکار داریم. از آرایه برای دسته بندی کردن آبجکت ها، جستجو، مرتب سازی، شکستن رشته ها و ... استفاده می کنیم.

اگر بخواهیم روی تمامی مقادیر موجود در یک آرایه، منطقی را پیاده کنیم، می توانیم از حلقه for استفاده کنیم. مثال های زیر را درنظر بگیرید.

آرایه ای از اعداد صحیح دارید و قصد دارید میانگین این اعداد را حساب کنید.

const numbers = [10, 25, 32, 48, 15, 6];

لیستی از دانش آموزان با فرمت زیر دارید و قصد دارید به هر آبجکت کلید جدیدی برای سن محاسبه شده دانش آموز اضافه کنید.

const students = [ { name: &quotAli Rafati&quot, class: &quotA1&quot, birth_year: 1995}, {name: &quotReza Molaei&quot, class: &quotA1&quot, birth_year: 1994}, {name: &quotSadegh Ahmadi&quot, class: &quotA2&quot, birth_year: 1996} ];

لیستی از اسامی کاربران دارید و می خواهید حرف اول تمامی آنها بزرگ نمایش داده شود.

const users = ['ali', 'reza', 'sara', 'mohammad']

در مثال های ذکر شده ما نیاز به پیمایش تمامی مقادیر موجود در لیست داریم، تا بتوانیم به نتیجه موردنظر برسیم. اما تنها گزینه موجود استفاده از حلقه for نیست. راه های جایگزین بهتری وجود دارد!


متد map

فرض کنید لیستی از آبجکت ها را دارید، که می خواهید مقدار جدیدی به همه آیتم های آن اضافه کنید (مثال افزودن سن دانش آموز براساس سال تولد) و یا لیستی از مقادیری دارید که می خواهید تغییری روی همه آن ها اعمال کنید (مثال بزرگ کردن حرف اول اسامی کاربران). در این گونه مسائل می توانید از متد map کمک بگیرید.

مثال 1: محاسبه سن دانش آموز و اضافه کردن آن به آبجکت آن ها

برای اینکه به خوبی متوجه مزایای متد map شوید، ابتدا مسئله را با استفاده از حلقه for حل می کنیم.

const studentsWithAge = []; const currentYear = new Date().getFullYear(); for (let index = 0; index < students.length; index++) { const age = currentYear - students[index].birth_year; studentsWithAge.push({ ...students[index], age }); }

در ابتدا یک آرایه جدید با نام studentsWithAge تعریف کرده ایم، که قرار است لیست دانش آموزان همراه با سن آن ها را در خود نگه دارد. با استفاده از for یک پیمایش کلی روی تمامی آبجکت های دانش آموزان داریم، سن دانش آموز را محاسبه کرده و به لیست جدید دانش آموزان اضافه می کنیم.

حل مسئله با استفاده از متد map به صورت زیر خواهد بود.

const currentYear = new Date().getFullYear(); const studentsWithAge = students.map(student => { const age = currentYear - student.birth_year; return { ...student, age }; });

کد نوشته شده کوتاه تر شده و خوانایی بالاتری نسبت به روش حل قبلی دارد.

متد map چگونه کار می کند؟

متد map یک callback function دریافت می کند که شامل سه پارامتر است. پارامتر اول مقدار فعلی حلقه، پارامتر دوم ایندکس جاری حلقه و پارامتر سوم همان آرایه ای است که متد map روی آن فراخوانی شده است.

const newItems = items.map((item, index, array) => { return newItem; })

تابع ارسال شده به متد map روی تمامی آیتم های موجود در لیست اجرا می شود و باید یک آیتم جدید را به عنوان مقدار تغییریافته برگرداند. تمامی مقادیر ارسال شده نهایتا از متد map برگردانده شده و به متغیر مدنظر (در این تکه کد newItems) نسبت داده می شود.

مثال های دیگری از مسائل حل شده با map

مثال 2: به توان 2 رساندن تمام اعداد موجود در لیست

const numbers = [1, 2, 3, 4]; const numbersPowerTwo = numbers.map(number => Math.pow(number, 2)); console.log(numbers); //[1,2,3,4] console.log(numbersPowerTwo); //[1,4,9,16]

نکات موجود در تکه کد بالا

  • همانطور که در خروجی کد می بینید، لیست اصلی numbers هیچ تغییری نکرده است، اعداد پس از آنکه به توان 2 رسیده اند، به لیست جدیدی به نام numbersPowerTwo اضافه شده اند.
  • با توجه به اینکه در این مسئله تنها می خواهیم اعداد را به توان دو برسانیم، یعنی در هر پیمایش تنها مقدار فعلی حلقه را نیاز داریم، نیازی به پارامترهای دوم و سوم تابع کال بک نداریم.
  • با توجه به اینکه از Arrow function استفاده شده است و آن را در یک خط نوشته ایم نیازی به کلمه کلیدی return نداریم.

مثال 3: بزرگ کردن حرف اول تمامی اسامی کاربران

const users = [&quotali&quot, &quotreza&quot, &quotsara&quot, &quotmohammad&quot]; const capitalUsers = users.map(user => firstCharToUpper(user));

متد filter

فرض کنید قصد داریم لیستی را براساس شرطی فیلتر کنیم و تنها آیتم هایی از لیست را در خروجی داشته باشیم که در شرط موردنظر صدق می کنند.

مثال اول: در لیستی از اعداد صحیح تنها اعداد فرد را می خواهیم.

در این مثال هم ابتدا با for مسئله را حل می کنیم.

const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; const oddNumbers = []; for (let index = 0; index < numbers.length; index++) { if (numbers[index] % 2 !== 0) { oddNumbers.push(numbers[index]); } }

مانند مثال قبلی حل شده با for ابتدا یک آرایه جدید برای اعداد فرد در نظر می گیریم، در حلقه تعریف شده با یک شرط تعیین می کنیم که چه اعدادی می توانند به آرایه جدید اضافه شوند.

حل مسئله با استفاده از filter به صورت زیر خواهد بود.

const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; const oddNumbers = numbers.filter(function(number) { return number % 2 !== 0; });

متد filter چگونه کار می کند؟

این متد هم مانند map یک تابع callback دریافت می کند که شامل 3 پارامتر است، پارامتر اول مقدار فعلی حلقه، پارامتر دوم ایندکس فعلی و پارامتر سوم آرایه ای است که متد filter روی آن اعمال شده است.

const filteredItems = items.filter((item, index, array) => { return true / false; });

همانطور که می بینید مقدار بازگشتی تابع کال بک یک مقدار Boolean (شرطی) است. متد filter این شرط را روی تمامی آیتم های آرایه بررسی می کند، اگر true برگردانده شود مقدار فعلی به خروجی نهایی ارسال می شود، در غیر این صورت آن مقدار نادیده گرفته می شود.

مثال دو: لیستی از دانش آموزانی که متولد 1995 به بعد هستند.

const filteredStudents = students.filter(student => students.birth_year > 1995);

نکات موجود در تکه کد بالا

  • با توجه به اینکه در این مسئله نیازی به استفاده از ایندکس و آرایه اورجینال در تابع callback نداشتیم، آن ها را حذف کردیم.
  • با توجه به استفاده از Arrow function یک خطی قبل از شرط فیلتر، نیازی به کلمه کلیدی return نداریم.

مثال 3: فیلتر رشته هایی که in دارند

const strings = [&quothello&quot, &quotcome in&quot, &quotinterface&quot, &quotincome&quot, &quotat school&quot]; const stringsWithIn = strings.filter(str => str.includes(&quotin&quot));

نکات مهم:

1. متدهای map و filter را می توان پشت سر هم و زنجیره وار اجرا کرد.

مثال: در آرایه ای که از دانش آموزان داشتیم، می خواهیم کاربرانی را نمایش دهیم که بیش از 25 سال سن دارند.

برای حل این مسئله ابتدا باید کلید جدیدی به نام age به هر آبجکت اضافه کنیم (متد map)، سپس با استفاده از متد filter روی مقدار age شرط بگذاریم.

const currentYear = new Date().getFullYear(); const filteredStudents = students .map(student => { const age = currentYear - student.birth_year; return { ...student, age }; }) .filter(student => student.age > 25);

2. با استفاده از متدهای map و filter به مقدار فعلی در هر پیمایش دسترسی داریم و نیازی نداریم با استفاده از ایندکس و آرایه به آن برسیم.

3. لیستی که متدهای map و filter روی آن فراخوانی شده اند، بدون تغییر باقی می ماند.

4. دردسر ایجاد یک آرایه جدید و push کردن و ... دیگر وجود ندارد.


mapfilterjavascript
شاید از این پست‌ها خوشتان بیاید