آموزش نحوۀ حذف اِلِمان‌های تکراری آرایه‌ها در جاوااسکریپت

در این مقاله قصد داریم تا به بررسی چند روش متفاوت به منظور حذف یکسری آیتم تکراری از میان اِلِمان‌های یک آرایه در زبان برنامه‌نویسی جاوااسکریپت بپردازیم به طوری که در نهایت یک آرایه با اِلِمان‌های منحصربه‌فرد داشته باشیم (جهت آشنایی با مفهوم آرایه‌ و کاربردهای آن در زبان برنامه‌نویسی جاوااسکریپت توصیه می‌کنیم به مقالۀ آشنایی با مفهوم آرایه و روش‌های ساخت آن مراجعه نمایید.)

به‌کارگیری آبجکت Set
یکی از روش‌های بسیار ساده و رایج به منظور حذف آیتم‌های تکراری از میان اِلِمان‌های یک آرایه به‌کارگیری آبجکت Set است. در واقع، کیورد Set در نسخۀ ES6 از این زبان معرفی شده و به منظور ساخت آبجکت‌های جدیدی مورد استفاده قرار می‌گیرد که با به‌کارگیری آن‌ها می‌توان یکسری مقدار منحصربه‌فرد با انواع مختلف را ذخیره و نگهداری کرد.

در همین راستا، ابتدا یک آبجکت جدید از نوع Set ساخته و آرایۀ مد نظر خود را به عنوان آرگومان ورودی به آن می‌دهیم و همان‌طور که اشاره کردیم، این آبجکت صرفاً مقادیر منحصربه‌فرد را شامل می‌شود که از داخل آن تمامی اِلِمان‌های تکراری از آرایۀ مذکور حذف می‌شوند و در گام بعدی آبجکت حاصله را مجدداً به آبجکتی از جنس آرایه تبدیل می‌کنیم که برای این منظور نیز اپراتور ... را مورد استفاده قرار می‌دهیم که اصطلاحاً Spread نامیده می‌شود (جهت آشنایی با سایر اپراتورها در این زبان می‌توانید به مقالۀ درآمدی بر اپراتورها در جاوااسکریپت مراجعه کنید.)

حال با توجه به آنچه گفته شد، کد زیر را به منظور حذف اِلِمان‌های تکراری از یک آرایۀ دلخواه و با به‌کارگیری آبجکتی از نوع Set مد نظر قرار می‌دهیم:

const array = ['a', 1, 2, 'a', 'a', 3];
const uniqueSet = new Set(array);
const backToArray = [...uniqueSet];

در کد فوق، ابتدا آرایه‌ای متشکل از اِلِمان‌های مختلف تعریف کرده و آن را به متغیری تحت عنوان array منتسب کرده‌ایم و در ادامه آبجکت جدیدی از نوع Set ساخته و آرایۀ فوق‌الذکر را به عنوان آرگومان ورودی به آن داده‌ایم؛ بدین ترتیب آبجکت Set آیتم‌های تکراری در آرایۀ مد نظر را حذف کرده و خروجی را در متغیری تحت عنوان uniqueSet نگهداری می‌کند. از این پس آبجکتی از نوع Set و متشکل از چند اِلِمان منحصربه‌فرد داریم که در سطر بعد با به‌کارگیری اپراتور ... نوع آن را به آرایه تغییر داده و نتیجه را در متغیری به نام backToArray ذخیره کرده‌ایم که خروجی حاصل از کد فوق بدین ترتیب خواهد بود:

['a', 1, 2, 3]

همان‌طور که می‌بینید، آرایه‌ای متشکل از اِلِمان‌های منحصربه‌فرد داریم. همچنین به منظور تبدیل آبجکت Set به آبجکتی از جنس آرایه نیز می‌توان متد از پیش تعریف‌شدۀ ()Array.from را مورد استفاده قرار داد که هر یک از اِلِمان‌های آرگومان ورودی را به آبجکتی از جنس آرایه تبدیل می‌کند که برای این منظور کد مثال قبل را بدین صورت تغییر می‌دهیم:

const array = ['a', 1, 2, 'a', 'a', 3];
Array.from(new Set(array));

در کد فوق، آرایه‌ای متشکل از چند اِلِمان مختلف تعریف کرده و آن را به متغیری تحت عنوان array منتسب کرده‌ایم و در ادامه با به‌کارگیری کیورد new آبجکتی از نوع Set ساخته و آرایهٔ تعریف‌شده را به عنوان آرگومان ورودی به آن داده‌ایم که منجر بدین می‌شود تا اِلِمان‌های تکراری از آرایۀ مد نظر حذف شوند که در ادامه آبجکتی از نوع Set و متشکل از چند اِلِمان منحصربه‌فرد داریم که خروجی حاصل از آن را به متد ()Array.from می‌دهیم تا در نهایت آرایه‌ای از اِلِمان‌های غیرتکراری و منحصربه‌فرد داشته باشیم. خروجی حاصل از کد فوق بدین ترتیب خواهد بود:

['a', 1, 2, 3]

همانطور که ملاحظه می‌کنید، در این مورد نیز نتیجۀ حاصل آبجکتی از جنس آرایه و متشکل از اِلِمان‌های منحصربه‌فرد می‌باشد.

استفاده از متد ()filter
در این روش از متدهای به اصطلاح Built-in تحت عناوین ()indexOf  و ()filter استفاده خواهیم کرد. در همین راستا، ابتدا نیاز است تا نحوۀ عملکرد متد ()indexOf را تشریح کنیم. در واقع، این متد بدین صورت عمل می‌کند که یک آرگومان ورودی گرفته و در آرایۀ مربوطه به دنبال اندیس آن می‌گردد و در ادامه اندیس مربوط به اولین اِلِمان پیداشده را در خروجی ریترن می‌کند که برای درک بهتر نحوۀ کار این متد مثال زیر را در ادامه آورده‌ایم:

const array = ['a', 1, 2, 'a', 'a', 3];
array.indexOf('a');

در کد فوق، آبجکتی از جنس آرایه و متشکل از چند اِلِمان دلخواه تعریف کرده و آن را به متغیری به نام array منتسب کرده‌ایم و در سطر بعد متد ()indexOf را روی این آبجکت فراخوانی کرده و گفته‌ایم که اندیس مربوط به اولین اِلِمان با مقداری معادل استرینگ «a» داخل آرایه را در خروجی ریترن کند که در خروجی خواهیم داشت:

0

همان‌طور که انتظار داشتیم، اولین اِلِمان با مقداری معادل استرینگ «a» در آرایۀ فوق به خانۀ شمارۀ صفرم تعلق دارد و عدد صفر در معرض دید ما قرار گرفته است.

حال به تشریح نحوۀ عملکرد متد ()filter می‌پردازیم. در واقع، این متد آرایه‌ای جدید ساخته و اِلِمان‌هایی از آرایۀ اصلی که با شرایط تعریف‌شده مطابقت داشته باشند را در آن نگهداری می‌کند؛ به عبارت دیگر، این متد هر یک از اِلِمان‌های آرایه را به عنوان ورودی گرفته و هر یک را چک می‌کند تا در نهایت اِلِمان‌هایی را به آرایۀ جدید اضافه کند که با شرایط تعیین‌شده مطابقت دارند. در ادامه متد ()filter را به منظور حذف اِلِمان‌های تکراری از آرایۀ مثال قبل بدین صورت پیاده‌سازی می‌کنیم:

const array = ['a', 1, 2, 'a', 'a', 'a', 3];
array.filter((item, index) => {
    console.log(item, index, array.indexOf(item), array.indexOf(item) === index, );
    return array.indexOf(item) === index
});

در کد فوق، آبجکتی از جنس آرایه ایجاد کرده و چند اِلِمان مختلف به آن اختصاص می‌دهیم و در ادامه متدی به نام ()filter ساخته‌ایم که در آن دو پارامتر ورودی تحت عناوین item و index تعریف کرده‌ایم که به ترتیب به منظور نگهداری مقدار هر یک از اِلِمان‌های آرایه و اندیس مربوط به آن‌ها مورد استفاده قرار می‌گیرند و در سطر بعد گفته‌ایم به ترتیب مقادیر هر یک از اِلِمان‌های آرایه، اندیس مربوط به هر اِلِمان، اندیس مربوط به اولین مقدار مشاهده‌شده از اِلِمان مد نظر در آرایه و در نهایت مقدار بولین مربوط به مقایسۀ دو پارامتر دوم و سوم را در خروجی چاپ کند؛ به عبارت دیگر، پارامتر ورودی چهارم در صورتی مقدار true می‌گیرد که تنها یک مقدار از اِلِمان‌های مد نظر در آرایۀ اصلی داشته باشیم به طوری که اندیس مربوط به اِلِمان مد نظر برابر با اندیس اولین مقدار مشاهده‌شده از آن در آرایۀ فوق‌الذکر باشد. در سطر آخر نیز گفته‌ایم مقادیر هر یک از اِلِمان‌هایی که مقدار بولین مربوط به آن‌ها برابر با true است را در خروجی ریترن کند که خروجی حاصل از این کد را در قالب جدولی به صورت زیر آورده‌ایم:

Condition indexOf Index Item
true 0 0 a
true 1 1 1
true 2 2 2
false 0 3 a
false 0 4 a
false 0 5 a
true 3 6 6

در نهایت، بر اساس آنچه در بالا توضیح دادیم، آرایه‌ای در خروجی داریم که مقدار بولین مربوط به اِلِمان‌های آن برابر با true است:

['a', 1, 2, 3]

همان‌طور که می‌بینید، آرایه‌ای جدید با اِلِمان‌های منحصربه‌فرد داریم که مقادیر تکراری متعلق به آرایۀ اصلی از آن حذف شده‌اند.

نحوۀ دستیابی به اِلِمان‌های تکراری آرایه
همچنین برای دستیابی به اِلِمان‌های تکراری آرایه می‌توانیم متد ()filter را مورد استفاده قرار دهیم که برای این منظور نیاز است تا شرط تعریف‌شده در مثال قبل را بدین صورت تغییر دهیم:

const array = ['a', 1, 2, 'a', 'a', 'a', 3];
array.filter((item, index) => {
    console.log(item, index, array.indexOf(item), array.indexOf(item) !== index, );
    return array.indexOf(item) !== index
});

نحوۀ عملکرد کد فوق نیز مشابه مثال قبل است با این تفاوت که در این مثال گفته‌ایم تمامی اِلِمان‌هایی را در خروجی ریترن کند که اندیس مربوط به آن‌ها در آرایۀ اصلی با اندیس اولین مقدار مشاهده‌شده از آن اِلِمان برابر نباشد که بدین ترتیب مقدار بولین پارامتر ورودی چهارم زمانی برابر با true خواهد بود که اندیس اِلِمان مد نظر برابر با اندیس اولین مقدار پیداشده از این اِلِمان در آرایه نباشد؛ به عبارت دیگر، اِلِمان‌هایی در خروجی ریترن می‌شوند که در آرایۀ مد نظر تکراری هستند. به طور کلی، خروجی حاصل از اجرای کد فوق در جدول زیر ارائه شده است:

Condition indexOf Index Item
false 0 0 a
false 1 1 1
false 2 2 2
true 0 3 a
true 0 4 a
true 0 5 a
false 3 6 6

در نهایت بر اساس آنچه در بالا توضیح دادیم، آرایه‌ای در خروجی داریم که اندیس هر یک از آن‌ها با اندیس اولین اِلِمان پیداشده از آیتم‌های مذکور برابر نباشند:

['a', 'a', 'a']

همان‌طور که ملاحظه می‌شود، آرایه‌ای جدید با اِلِمان‌های تکراری داریم که مقادیر غیرتکراری متعلق به آرایۀ اصلی از آن حذف شده‌اند.

به‌کارگیری متد ()reduce
متد از پیش تعریف‌شدۀ ()reduce برای کاستن تعداد اِلِمان‌های آرایه استفاده می‌شود به طوری که یک آرایۀ جدید ساخته و بر اساس شرایط تعیین‌شده یکسری مقادیر مربوط به آرایۀ اصلی را حذف کرده و مابقی را در آن نگهداری می‌کند.

در مثال زیر، شرط تعیین‌شده به منظور حذف برخی اِلِمان‌های مربوط به آرایۀ اصلی بدین صورت می‌باشد که یک اِلِمان از آرایۀ اصلی برداشته و در صورتی آن را به آرایۀ جدید اضافه می‌کند که آیتم مربوطه قبلاً در این آرایه وجود نداشته باشد؛ به عبارت بهتر، آیتم‌های غیرتکراری به آرایۀ جدید افزوده می‌شوند و در صورت تکراری بودن اِلِمان مذکور آخرین مقادیر ذخیره‌شده در آرایۀ جدید در خروجی ریترن می‌شود که به منظور پیاده‌سازی این فانکشن کدی مانند زیر خواهیم داشت:

const array = ['a', 1, 2, 'a', 'a', 3];
array.reduce((unique, item) => {
    console.log(item, unique, unique.includes(item), unique.includes(item) ? unique : [...unique, item], );
    return unique.includes(item) ? unique : [...unique, item]
}, []);

در کد فوق آبجکتی از جنس آرایه به نام array ساخته و یکسری اِلِمان به آن اختصاص داده‌ایم و در سطر بعد فانکشن ()reduce را با دو پارامتر ورودی تحت عناوین unique و item فراخوانی کرده‌ایم که در آن گفته‌ایم به ترتیب مقادیر زیر را در خروجی ریترن کند:

- هر یک از اِلِمان‌های آرایۀ اصلی
- آرایه‌ای تحت عنوان unique که متشکل از اِلِمان‌های آرایهٔ اصلی پیش از حذف است (در واقع، اِلِمان‌های آرایه اصلی را که تک‌به‌تک از آن خارج کرده و به آرایۀ جدید اضافه می‌کند.)
- مقدار بولین مربوط به شرط مسئله که در آن گفته‌ایم چنانچه آیتم مد نظر از آرایۀ اصلی در آرایۀ جدیدِ unique موجود بود، مقدار true و در غیر این صورت مقدار false را در خروجی ریترن کند.
- و آرایۀ نهایی با حذف مقادیر تکراری

در نهایت، خروجی حاصل از اجرای کد فوق به ترتیب زیر خواهد بود:

(Array (After Reducer Function Push to Array (Array (Before Reducer Function Item
['a'] true [ ] a
[a', 1'] true ['a'] 1
[a', 1, 2'] true [a', 1'] 2
[a', 1, 2'] false [a', 1, 2'] a
[a', 1, 2'] false [a', 1, 2'] a
[a', 1, 2, 3'] true [a', 1, 2'] 3

همان‌طور که می‌بینید، ابتدا آیتم اول را از آرایۀ اصلی برداشته و چک می‌کنیم که آیا در آرایۀ منتسب به متغیر unique مقداری معادل استرینگ «a» وجود دارد یا خیر که می‌بینیم آرایۀ unique خالی بوده و از همین روی خروجی دستور شرطی true می‌شود و اِلِمان مد نظر به آرایۀ جدید افزوده می‌شود. به همین ترتیب برای باقی اِلِمان‌ها شرط تعیین‌شده چک می‌شود که اگر اِلِمان مد نظر تکراری باشد به آرایۀ جدید افزوده نمی‌شود که در چنین شرایطی آخرین مقادیر منتسب به آرایۀ جدید در خروجی ریترن می‌شود و در نهایت داریم:

['a', 1, 2, 3]

همان‌طور که می‌بینید، آرایه‌ای جدید داریم که مقادیر تکراری مربوط به آرایۀ اصلی از آن حذف شده‌اند.

جمع‌بندی
در این مقاله به بیان برخی از روش‌های رایج جهت حذف اِلِمان‌های تکراری از آرایه‌ها در زبان جاوااسکریپت پرداختیم و نحوۀ پیاده‌سازی هر یک را در قالب مثالی کاربردی بررسی کردیم اما توجه داشته باشیم که روش‌های بسیاری برای این منظور می‌توان پیاده‌سازی کرد که متناسب با موقعیت‌های مختلف به کار گرفته می‌شوند و نیازمند مطالعه، تمرین و تحقیق بیشتر هستند.

نظرات

پیشنهادات بیشتر سکان بلاگ برای شما

اگر login نکردی برامون ایمیلت رو بنویس: