ترتيب مصفوفة الكائنات حسب الخاصية النصية: تحليل سؤال شائع من Stack Overflow
\n\nتخيل: لديك قائمة من المستخدمين أو المنتجات أو المقالات. كل عنصر هو كائن بمجموعة من الخصائص: الاسم، السعر، التاريخ، التقييم. وتحتاج إلى ترتيب كل هذا، مثلاً، حسب اسم العائلة بترتيب أبجدي. مهمة تبدو بسيطة، لكنها في الواقع تحمل بعض المفاجآت. ليس من المستغرب أن السؤال "Sort array of objects by string property value" على Stack Overflow حصل على آلاف المشاهدات وعشرات الإجابات.
\n\nفي هذه المقالة، لن نقدم فقط كودًا جاهزًا. سنقوم بتحليل 5 طرق للترتيب، من الأساسي إلى المتقدم، وسنكشف عن الأخطاء النموذجية ونوضح كيفية تجنبها. في النهاية، ستتمكن من ترتيب أي بيانات بكل سهولة.
\n\nما هو ترتيب مصفوفة الكائنات في جافا سكريبت؟
\n\nفي جافا سكريبت، هناك طريقة مدمجة Array.prototype.sort(). لكن مع الكائنات، لا تعمل بشكل بديهي. إذا استدعيت sort() بدون وسائط، فسيحاول مقارنة العناصر كسلاسل نصية. بالنسبة للأرقام، هذا يعطي مفاجأة: [1, 20, 3].sort() سيعيد [1, 20, 3]، وليس [1, 3, 20]. بالنسبة للكائنات، ستكون فوضى تامة.
لذلك نحتاج إلى دالة مقارنة (comparator). تأخذ عنصرين وتعيد:
\n- \n
- رقمًا سالبًا إذا كان العنصر الأول أصغر من الثاني؛ \n
- 0 إذا كانا متساويين؛ \n
- رقمًا موجبًا إذا كان الأول أكبر. \n
إليك الهيكل الأساسي لترتيب مصفوفة الكائنات حسب خاصية سلسلة نصية:
\n\n// المصفوفة الأصلية\nconst users = [\n { name: 'إيفان', age: 25 },\n { name: 'آنا', age: 30 },\n { name: 'بوريس', age: 22 }\n];\n\n// الترتيب حسب الحقل name\nusers.sort((a, b) => {\n if (a.name < b.name) return -1;\n if (a.name > b.name) return 1;\n return 0;\n});\n\nconsole.log(users);\n// [{ name: 'آنا', age: 30 }, { name: 'بوريس', age: 22 }, { name: 'إيفان', age: 25 }]\n\nهذا الكود يعمل، لكنه ضخم. دعنا نرى كيف نجعله أكثر أناقة.
\n\n5 طرق لترتيب مصفوفة الكائنات حسب السلسلة النصية
\n\nالطريقة 1: دالة المقارنة التقليدية
\n\nالطريقة الأكثر وضوحًا. مناسبة لأي سلاسل نصية، بما في ذلك السيريلية، بشرط استخدام الترتيب الأبجدي الصحيح. المقارنة عبر < و > تراعي رموز Unicode، مما يعطي نتيجة غير متوقعة للغة الروسية: حرف «ё» سيظهر في نهاية الأبجدية، وحرف «я» سيكون بجانب «а».
const products = [\n { title: 'Яблоко', price: 50 },\n { title: 'Ёлка', price: 200 },\n { title: 'Ананас', price: 150 }\n];\n\n// المشكلة: 'Ёлка' ستوضع بعد 'Яблоко'\nproducts.sort((a, b) => {\n if (a.title < b.title) return -1;\n if (a.title > b.title) return 1;\n return 0;\n});\n\nمتى تستخدم: للسلاسل النصية الإنجليزية، حيث يتطابق الترتيب الأبجدي مع Unicode.
\n\nالطريقة 2: localeCompare — منقذ السيريلية
\n\nطريقة String.prototype.localeCompare() تراعي قواعد الترتيب للغة محددة. للروسية، نمرر 'ru'.
users.sort((a, b) => a.name.localeCompare(b.name, 'ru'));\n\nconsole.log(users);\n// [{ name: 'آنا', age: 30 }, { name: 'بوريس', age: 22 }, { name: 'إيفان', age: 25 }]\n\nهذا الكود أنظف وأقصر ويعالج بشكل صحيح الحروف «ё» و «й» وغيرها. إذا كنت بحاجة إلى ترتيب تنازلي، فقط قم بتبديل a و b:
users.sort((a, b) => b.name.localeCompare(a.name, 'ru'));\n\nمتى تستخدم: دائمًا عند العمل مع السيريلية أو البيانات متعددة اللغات.
\n\nالطريقة 3: الترتيب مع مراعاة حالة الأحرف
\n\nافتراضيًا، localeCompare حساس لحالة الأحرف: «apple» ستوضع قبل «Banana»، لأن الحرف الصغير له