العناصر الفريدة في مصفوفة JavaScript: إزالة التكرارات من الداخل

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مصفوفة مكررة: لماذا جمعت هذه المهمة آلاف المشاهدات على Stack Overflow

\n\n

تخيل: أنت تكتب متجرًا إلكترونيًا، ويضيف المستخدم منتجات إلى سلة التسوق. ولكن بسبب خطأ أو خلل، يظهر نفس الهاتف iPhone في القائمة ثلاث مرات. أو تقوم بتحليل قائمة من العلامات من قاعدة البيانات، وتجد أن "JavaScript" تتكرر 15 مرة متتالية. ماذا تفعل؟ صحيح — اترك القيم الفريدة فقط.

\n\n

سؤال "Get all unique values in a JavaScript array (remove duplicates)" على Stack Overflow جمع مئات الآلاف من المشاهدات. وهذا ليس من قبيل الصدفة. تبدو المهمة بسيطة، ولكن تحت الغطاء تختبئ ترسانة كاملة من الأساليب: من الأسطر الفردية في ES6 الحديث إلى الحيل الذكية مع filter و indexOf. في هذه المقالة، لن نقدم حلولًا جاهزة فحسب، بل سنشرح كيف يعمل كل منها على مستوى محرك JavaScript.

\n\n

هل أنت مستعد للنظر تحت الغطاء؟ هيا بنا!

\n\n
\n\n

الطريقة رقم 1: Set — ملك الأداء

\n\n

الطريقة الأكثر أناقة وسرعة للحصول على القيم الفريدة في مصفوفة JavaScript هي استخدام كائن Set. ظهر في ES6 وهو مصمم حرفيًا لهذه المهمة.

\n\n
const numbers = [1, 2, 2, 3, 4, 4, 5];\nconst uniqueNumbers = [...new Set(numbers)];\n\nconsole.log(uniqueNumbers); // [1, 2, 3, 4, 5]
\n\n

كيف يعمل هذا تحت الغطاء؟

\n

كائن Set يخزن القيم الفريدة فقط. عندما نمرر المصفوفة إلى المُنشئ new Set(numbers)، يمر محرك JavaScript عبر كل عنصر ويضيفه إلى جدول التجزئة الداخلي. إذا كانت القيمة موجودة بالفعل — يتم تجاهلها. ثم يقوم عامل الانتشار ... بتحويل Set مرة أخرى إلى مصفوفة.

\n\n

لماذا هذا سريع؟ لأن البحث والإدراج في Set يتمان في وقت ثابت O(1). بالنسبة لمصفوفة من 10,000 عنصر، سيكون الفرق مع الطرق الأخرى هائلاً.

\n\n

هام: Set يحافظ على ترتيب العناصر، ولكنه يعمل فقط مع الأنواع البدائية (الأرقام، السلاسل النصية، القيم المنطقية). بالنسبة للكائنات، تتم المقارنة حسب المرجع وليس حسب المحتوى.

\n\n

متى تستخدم؟

\n
    \n
  • إذا كانت المصفوفة تتكون من أرقام أو سلاسل نصية.
  • \n
  • إذا كانت سرعة معالجة المصفوفات الكبيرة مهمة.
  • \n
  • إذا كنت تكتب كودًا حديثًا ولا تخشى ES6.
  • \n
\n\n
\n\n

الطريقة رقم 2: filter + indexOf — كلاسيكيات هذا النوع

\n\n

هذه الطريقة هي المخضرم في JavaScript. تعمل في جميع المتصفحات بدون polyfills ولا تزال شائعة على Stack Overflow.

\n\n
const numbers = [1, 2, 2, 3, 4, 4, 5];\nconst uniqueNumbers = numbers.filter((value, index, arr) => {\n  return arr.indexOf(value) === index;\n});\n\nconsole.log(uniqueNumbers); // [1, 2, 3, 4, 5]
\n\n

تحليل المنطق

\n

طريقة filter تنشئ مصفوفة جديدة، تاركة فقط العناصر التي يُرجع لها callback القيمة true. داخل callback نتحقق: هل الفهرس الحالي هو أول ظهور لهذه القيمة في المصفوفة؟ إذا كان الجواب نعم — نترك العنصر. إذا كانت القيمة قد ظهرت من قبل — سيعيد indexOf فهرسًا أصغر، ولن يتحقق الشرط، وسيتم تجاهل التكرار.

\n\n

المأزق: indexOf يمر عبر المصفوفة من البداية في كل مرة. هذا يعطي تعقيدًا O(n²). بالنسبة للمصفوفات الصغيرة (حتى 1000 عنصر) الفرق غير ملحوظ، ولكن على 100,000 عنصر قد يتجمد المتصفح لثانية.

\n\n

متى تستخدم؟

\n
    \n
  • إذا كنت بحاجة لدعم المتصفحات القديمة (IE11).
  • \n
  • إذا كانت المصفوفة صغيرة.
  • \n
  • إذا كنت تريد عرض منطق عمل "أول ظهور" بشكل واضح.
  • \n
\n\n
\n\n

الطريقة رقم 3: reduce + المُراكم — المرونة والتحكم

\n\n

طريقة reduce تمنحك تحكمًا كاملاً في العملية. نحن نقرر بأنفسنا كيفية جمع النتيجة.

\n\n
const numbers = [1, 2, 2, 3, 4, 4, 5];\nconst uniqueNumbers = numbers.reduce((acc, value) => {\n  if (!acc.includes(value)) {\n    acc.push                

المدونات

توصيات الكتب