فرز المصفوفات في JavaScript: دليل متكامل لدالة Sort() وأمثلة عملية
في عالم تطوير الويب، تُعد معالجة البيانات جزءًا أساسيًا من أي تطبيق. غالبًا ما نحتاج إلى تنظيم البيانات المخزنة في المصفوفات (Arrays) بطريقة معينة لتسهيل عرضها أو معالجتها. لحسن الحظ، توفر لغة JavaScript دالة مدمجة قوية تُعرف باسم sort()، والتي تُمكننا من فرز عناصر المصفوفة بسهولة. ومع ذلك، قد تختلف أنواع البيانات داخل المصفوفات (مثل السلاسل النصية أو الأرقام)، مما يعني أن استخدام دالة sort() بمفردها قد لا يكون دائمًا الحل الأمثل أو يعطي النتائج المتوقعة.
في هذا الدليل الشامل، سنتعمق في كيفية استخدام دالة sort() لفرز المصفوفات في JavaScript، مع التركيز على التعامل الصحيح مع السلاسل النصية والأرقام، مدعومين بأمثلة برمجية واضحة.
فرز المصفوفات النصية (Strings) في JavaScript
لنبدأ بالتعامل مع السلاسل النصية، وهو السيناريو الأكثر وضوحًا عند استخدام دالة sort(). عند تطبيق الدالة على مصفوفة تحتوي على سلاسل نصية، يتم فرز العناصر افتراضيًا بترتيب تصاعدي أبجدي (من الألف إلى الياء).
الفرز التصاعدي للسلاسل النصية
لنأخذ هذا المثال لمصفوفة من أسماء الفرق:
const teams = [
'Real Madrid' ,
'Manchester Utd' ,
'Bayern Munich' ,
'Juventus'
];
عند تطبيق دالة sort() عليها، ستُفرز العناصر أبجديًا:
teams.sort(); // ['Bayern Munich', 'Juventus', 'Manchester Utd', 'Real Madrid']
الفرز التنازلي للسلاسل النصية
إذا كنت تفضل فرز المصفوفة بترتيب تنازلي (من الياء إلى الألف)، يمكنك استخدام دالة reverse() بعد الفرز التصاعدي، أو مباشرة على المصفوفة المفرزة:
teams.reverse(); // ['Real Madrid', 'Manchester Utd', 'Juventus', 'Bayern Munich']
لاحظ أن دالة reverse() تعكس ترتيب العناصر الحالية في المصفوفة، لذا إذا طبقتها على مصفوفة مفرزة تصاعديًا، ستحصل على ترتيب تنازلي.
تحدي فرز المصفوفات الرقمية (Numbers) في JavaScript
للأسف، فرز الأرقام ليس بهذه البساطة كما هو الحال مع السلاسل النصية. إذا قمنا بتطبيق دالة sort() مباشرة على مصفوفة من الأرقام، فسنحصل على نتيجة غير متوقعة قد تبدو خاطئة للوهلة الأولى:
const numbers = [
3 ,
23 ,
12
];
numbers.sort(); // --> 12, 23, 3
لماذا لا تعمل دالة sort() بشكل صحيح مع الأرقام؟
في الواقع، الدالة تعمل، ولكن المشكلة تكمن في طريقة عمل JavaScript الافتراضية. تقوم JavaScript بفرز الأرقام أبجديًا (كأنها سلاسل نصية) وليس حسابيًا. دعنا نشرح هذا بالتفصيل:
تخيل أننا نتعامل مع أحرف 'A'=1، 'B'=2، و 'C'=3. إذا كانت لدينا مصفوفة من السلاسل النصية مثل ['C', 'BC', 'AB']، فإن JavaScript ستقوم بفرزها كالتالي:
const myArray = [
'C' ,
'BC' ,
'AB'
];
myArray.sort(); // ['AB', 'BC', 'C']
هذا الترتيب صحيح أبجديًا. وبالمثل، عندما تُطبق دالة sort() على الأرقام [3, 23, 12]، فإنها تتعامل معها كأنها سلاسل نصية: "3"، "23"، "12". وبناءً على الترتيب الأبجدي، يأتي "12" قبل "23"، ويأتي "23" قبل "3" (بسبب المقارنة بين الحرف الأول). لذا، تكون النتيجة [12, 23, 3]، وهو ترتيب خاطئ من الناحية العددية.
الحل الأمثل: دالة المقارنة (Compare Function)
لحسن الحظ، يمكننا تزويد دالة sort() بدالة مقارنة (compare function) مخصصة، والتي ستحل هذه المشكلة بفعالية. تتلقى دالة المقارنة وسيطين (a و b) وتقوم بإرجاع قيمة بناءً على مقارنتهما:
function (a, b) {
return a - b
}
تُعد هذه الدالة قوية لأن دالة sort() يمكنها التعامل مع القيم السالبة والصفر والموجبة بشكل صحيح. عند مقارنة قيمتين، تُرسل دالة sort() هاتين القيمتين إلى دالة المقارنة الخاصة بنا، ثم تقوم بفرز القيم وفقًا للقيمة المُرجعة:
- إذا كانت النتيجة سالبة (
a - b < 0)، يتم ترتيبaقبلb. - إذا كانت النتيجة موجبة (
a - b > 0)، يتم ترتيبbقبلa. - إذا كانت النتيجة صفرًا (
a - b === 0)، لا يحدث أي تغيير في الترتيب النسبي للعنصرين.
كل ما نحتاجه هو استخدام دالة المقارنة هذه داخل دالة sort().
فرز الأرقام تصاعدياً
لفرز الأرقام بترتيب تصاعدي، نستخدم a - b:
const numbers = [
3 ,
23 ,
12
];
numbers.sort( function (a, b) {
return a - b
}); // --> [3, 12, 23]
فرز الأرقام تنازلياً
إذا أردنا فرز الأرقام بترتيب تنازلي، نحتاج هذه المرة إلى طرح الوسيط الثاني (b) من الوسيط الأول (a)، أي b - a:
const numbers = [
3 ,
23 ,
12
];
numbers.sort( function (a, b) {
return b - a
}); // --> [23, 12, 3]
الخلاصة التقنية
كما رأينا، يمكن فرز عناصر المصفوفات بسهولة في JavaScript باستخدام دالة sort()، شريطة أن نعرف كيفية استخدامها بشكل صحيح. بينما تعمل الدالة بشكل مباشر وفعال مع السلاسل النصية، تتطلب معالجة الأرقام فهمًا لآلية الفرز الأبجدي الافتراضية لـ JavaScript، وتتطلب استخدام دالة مقارنة مخصصة. إن إتقان دالة المقارنة يفتح الباب أمام إمكانيات فرز أكثر تعقيدًا وتخصيصًا، مما يجعلها أداة لا غنى عنها لأي مطور JavaScript. تذكر دائمًا أن فهم سلوك الدالة الافتراضي هو مفتاح كتابة كود فعال وخالٍ من الأخطاء.