كيفية التحكم في ما إذا كانت الأحرف الكبيرة أو الصغيرة تأتي أولاً في الترتيب

استخدم خيار caseFirst في Intl.Collator لتحديد ترتيب الحالة عند فرز السلاسل النصية

مقدمة

عندما تقوم بترتيب مصفوفة من السلاسل النصية التي تختلف فقط في حالة الأحرف، تحتاج جافا سكريبت إلى تحديد أي إصدار يأتي أولاً. هل يجب أن تأتي apple قبل Apple، أم يجب أن تأتي Apple قبل apple؟ تختلف متطلبات هذا الترتيب من تطبيق لآخر.

بشكل افتراضي، يعتمد ترتيب السلاسل النصية التي تختلف فقط في حالة الأحرف على إعدادات اللغة والحساسية. في كثير من الحالات، يتم التعامل مع السلاسل النصية مثل apple وApple على أنها متساوية، مما يجعل ترتيبها غير متوقع. عندما يكون ترتيب حالة الأحرف مهمًا لتطبيقك، تحتاج إلى تحكم صريح في ما إذا كانت الأحرف الكبيرة أو الصغيرة تُرتب أولاً.

توفر واجهة برمجة التطبيقات Intl.Collator خيار caseFirst الذي يحدد ترتيب حالة الأحرف. يمكنك تكوين المرتب لوضع الأحرف الكبيرة قبل الأحرف الصغيرة، أو الأحرف الصغيرة قبل الأحرف الكبيرة، أو استخدام السلوك الافتراضي للغة. يشرح هذا الدرس كيفية عمل خيار caseFirst، ومتى يكون له تأثير، وكيفية استخدامه في سيناريوهات الترتيب العملية.

ماذا يفعل خيار caseFirst

يتحكم خيار caseFirst في ترتيب السلاسل النصية التي تختلف فقط في حالة الأحرف. وهو يقبل ثلاث قيم نصية: "upper"، "lower"، أو "false".

عند تعيينه إلى "upper"، تُرتب الأحرف الكبيرة قبل نظيراتها الصغيرة. تأتي السلسلة النصية Apple قبل apple.

عند تعيينه إلى "lower"، تُرتب الأحرف الصغيرة قبل نظيراتها الكبيرة. تأتي السلسلة النصية apple قبل Apple.

عند تعيينه إلى "false" (القيمة النصية، وليس القيمة المنطقية)، يستخدم المرتب ترتيب الحالة الافتراضي للغة. هذا هو السلوك الافتراضي عندما لا تحدد الخيار.

يؤثر خيار caseFirst فقط على السلاسل النصية المتطابقة باستثناء حالة الأحرف. تُرتب السلاسل النصية التي تختلف في أحرفها الأساسية وفقًا لقواعد الترتيب الأبجدي العادية بغض النظر عن هذا الإعداد.

كيف يعمل ترتيب الحالة الافتراضي

بدون تحديد خيار caseFirst، يستخدم المقارن السلوك الافتراضي الذي يعتمد على الإعدادات المحلية وإعدادات الحساسية.

const collator = new Intl.Collator('en-US');
const words = ['apple', 'Apple', 'APPLE'];

words.sort(collator.compare);

console.log(words);
// Output: ['apple', 'Apple', 'APPLE']

يعتمد ترتيب الإخراج على التنفيذ والإعدادات المحلية. مع إعدادات الحساسية الافتراضية، يأخذ المقارن في الاعتبار اختلافات الحالة، ولكن الترتيب المحدد لـ apple وApple وAPPLE يختلف.

تمتلك الإعدادات المحلية المختلفة اتفاقيات ترتيب حالة افتراضية مختلفة. تضع بعض الإعدادات المحلية الأحرف الصغيرة أولاً تقليديًا، بينما يضع البعض الآخر الأحرف الكبيرة أولاً. الاعتماد على السلوك الافتراضي ينتج نتائج غير متسقة عبر البيئات المختلفة.

وضع الأحرف الكبيرة أولاً باستخدام caseFirst upper

يضمن إعداد caseFirst: "upper" أن تأتي الأحرف الكبيرة دائمًا قبل مكافئاتها الصغيرة في النتائج المرتبة.

const collator = new Intl.Collator('en-US', { caseFirst: 'upper' });
const words = ['apple', 'Apple', 'banana', 'Banana'];

words.sort(collator.compare);

console.log(words);
// Output: ['Apple', 'apple', 'Banana', 'banana']

يقوم المقارن بالترتيب أبجديًا حسب الحرف الأساسي أولاً، ثم يطبق ترتيب الحالة داخل كل مجموعة. من بين الكلمات التي تبدأ بـ a، تأتي Apple قبل apple. من بين الكلمات التي تبدأ بـ b، تأتي Banana قبل banana.

هذا الترتيب مفيد عند عرض قوائم حيث يجب أن تظهر الأسماء المناسبة أو العناوين المكتوبة بأحرف كبيرة بشكل بارز قبل الأسماء الشائعة.

const collator = new Intl.Collator('en-US', { caseFirst: 'upper' });
const names = ['smith', 'Smith', 'jones', 'Jones'];

names.sort(collator.compare);

console.log(names);
// Output: ['Jones', 'jones', 'Smith', 'smith']

تظهر الأسماء المكتوبة بأحرف كبيرة قبل الإصدارات المكتوبة بأحرف صغيرة، مما يجعل من السهل التمييز بين الأسماء المناسبة والكلمات الشائعة في القوائم المختلطة.

وضع الأحرف الصغيرة أولاً باستخدام caseFirst lower

إن تعيين caseFirst: "lower" يضمن أن الأحرف الصغيرة تأتي دائمًا قبل نظيراتها الكبيرة في نتائج الفرز.

const collator = new Intl.Collator('en-US', { caseFirst: 'lower' });
const words = ['apple', 'Apple', 'banana', 'Banana'];

words.sort(collator.compare);

console.log(words);
// Output: ['apple', 'Apple', 'banana', 'Banana']

يقوم المقارن بالفرز أبجديًا أولاً، ثم يضع الإصدارات ذات الأحرف الصغيرة قبل الإصدارات ذات الأحرف الكبيرة داخل كل مجموعة أبجدية.

يتطابق هذا الترتيب مع الاتفاقيات حيث يعتبر النص ذو الأحرف الصغيرة أكثر قياسية أو محايدة، مع الاحتفاظ بالأحرف الكبيرة للتأكيد أو الحالات الخاصة.

const collator = new Intl.Collator('en-US', { caseFirst: 'lower' });
const tags = ['javascript', 'JavaScript', 'python', 'Python'];

tags.sort(collator.compare);

console.log(tags);
// Output: ['javascript', 'JavaScript', 'python', 'Python']

تظهر العلامات ذات الأحرف الصغيرة أولاً، وهو أمر مفيد عندما تمثل الأحرف الصغيرة الشكل القانوني وتكون إصدارات الأحرف الكبيرة اختلافات أقل شيوعًا.

استخدام caseFirst false للسلوك الافتراضي للغة

إن تعيين caseFirst: "false" (قيمة السلسلة) يطلب صراحةً ترتيب الحالة الافتراضي للغة. وهذا ينتج نفس النتيجة كما لو تم حذف الخيار تمامًا.

const collator = new Intl.Collator('en-US', { caseFirst: 'false' });
const words = ['apple', 'Apple', 'APPLE'];

words.sort(collator.compare);

console.log(words);
// Output depends on locale implementation

يعتمد ترتيب الإخراج على ما تعتبره اللغة قياسيًا. بعض اللغات تحدد الأحرف الكبيرة أولاً، والبعض الآخر يحدد الأحرف الصغيرة أولاً، وبعضها يعامل السلاسل المختلفة في الحالة على أنها متساوية.

هذا الخيار مفيد عندما تريد أن توضح صراحةً أنك تستخدم الإعدادات الافتراضية للغة بدلاً من حذف خيار التكوين عن طريق الخطأ.

متى لا يكون لـ caseFirst أي تأثير

يؤثر خيار caseFirst على المقارنة فقط عندما يسمح إعداد الحساسية باعتبار اختلافات الحالة مهمة. مع sensitivity: "base" أو sensitivity: "accent"، يتم تجاهل اختلافات الحالة تمامًا، مما يجعل خيار caseFirst غير ذي صلة.

const collator = new Intl.Collator('en-US', {
  sensitivity: 'base',
  caseFirst: 'upper'
});

const words = ['apple', 'Apple', 'APPLE'];

words.sort(collator.compare);

console.log(words);
// Output: ['apple', 'Apple', 'APPLE'] (or any order)

مع الحساسية الأساسية، يعامل المقارن جميع السلاسل الثلاث على أنها متساوية. ليس لخيار caseFirst أي تأثير لأن الحالة لا تؤخذ في الاعتبار على الإطلاق. تحافظ خوارزمية الفرز على الترتيب الأصلي للعناصر المتساوية (فرز مستقر)، لذلك يتطابق الإخراج مع ترتيب الإدخال.

لكي يكون لـ caseFirst تأثير، استخدم sensitivity: "case" أو sensitivity: "variant" (الافتراضي).

const collator = new Intl.Collator('en-US', {
  sensitivity: 'variant',
  caseFirst: 'upper'
});

const words = ['apple', 'Apple', 'APPLE'];

words.sort(collator.compare);

console.log(words);
// Output: ['APPLE', 'Apple', 'apple']

مع حساسية المتغير (التي تأخذ في الاعتبار جميع الاختلافات بما في ذلك الحالة)، يحدد خيار caseFirst ترتيب هذه السلاسل المختلفة في الحالة.

فرز الأسماء مع ترتيب متسق للحالة

عند فرز أسماء المستخدمين أو الأسماء الخاصة الأخرى، يضمن ترتيب الحالة المتسق نتائج متوقعة عبر تطبيقك.

const collator = new Intl.Collator('en-US', { caseFirst: 'upper' });

const users = [
  { name: 'alice' },
  { name: 'Alice' },
  { name: 'bob' },
  { name: 'Bob' }
];

users.sort((a, b) => collator.compare(a.name, b.name));

users.forEach(user => {
  console.log(user.name);
});
// الناتج:
// Alice
// alice
// Bob
// bob

يضع المرتب الأسماء ذات الأحرف الكبيرة قبل الإصدارات ذات الأحرف الصغيرة. يجعل هذا الترتيب من السهل رؤية الأسماء المناسبة مقابل الكلمات الشائعة في مجموعات البيانات المختلطة.

فرز أسماء الملفات مع ترتيب حالة متحكم به

تمتلك أنظمة الملفات سلوكيات مختلفة لحساسية الحالة. بعضها يعامل الأحرف الكبيرة والصغيرة على أنها متماثلة، والبعض الآخر يعاملها على أنها مختلفة. يضمن ترتيب الحالة الصريح أن قوائم الملفات المرتبة تتطابق مع توقعات المستخدم بغض النظر عن نظام الملفات الأساسي.

const collator = new Intl.Collator('en-US', { caseFirst: 'lower' });

const files = ['README.md', 'readme.md', 'index.js', 'Index.js'];

files.sort(collator.compare);

console.log(files);
// الناتج: ['index.js', 'Index.js', 'readme.md', 'README.md']

تظهر الإصدارات ذات الأحرف الصغيرة أولاً، مطابقة للعرف حيث تكون أسماء الملفات ذات الأحرف الصغيرة أكثر قياسية في الأنظمة الشبيهة بنظام يونكس.

دمج caseFirst مع الترتيب الرقمي

يعمل خيار caseFirst جنبًا إلى جنب مع خيارات الترتيب الأخرى مثل numeric. يمكنك فرز السلاسل النصية ذات الأرقام المضمنة مع التحكم في ترتيب الحالة.

const collator = new Intl.Collator('en-US', {
  numeric: true,
  caseFirst: 'upper'
});

const items = ['item1', 'Item1', 'item2', 'Item2', 'item10', 'Item10'];

items.sort(collator.compare);

console.log(items);
// الناتج: ['Item1', 'item1', 'Item2', 'item2', 'Item10', 'item10']

يطبق المرتب المقارنة الرقمية لأجزاء الأرقام وترتيب الحالة لأجزاء الحروف. يتم فرز العناصر حسب القيمة الرقمية أولاً (1، 2، 10)، ثم حسب الحالة داخل كل مجموعة رقمية.

استخدام مفتاح امتداد Unicode لـ caseFirst

يمكن أيضًا تعيين خيار caseFirst من خلال امتداد Unicode في معرّف اللغة باستخدام المفتاح kf. قيم الامتداد هي upper وlower وfalse.

const collator = new Intl.Collator('en-US-u-kf-upper');
const words = ['apple', 'Apple', 'banana', 'Banana'];

words.sort(collator.compare);

console.log(words);
// Output: ['Apple', 'apple', 'Banana', 'banana']

سلسلة اللغة en-US-u-kf-upper تحدد اللغة الإنجليزية الأمريكية مع ترتيب الحالة بالأحرف الكبيرة أولاً. هذا ينتج نفس النتيجة كتمرير { caseFirst: 'upper' } في كائن الخيارات.

عندما يحدد كل من امتداد Unicode وكائن الخيارات caseFirst، فإن كائن الخيارات يأخذ الأولوية.

const collator = new Intl.Collator('en-US-u-kf-upper', {
  caseFirst: 'lower'
});

const words = ['apple', 'Apple'];

words.sort(collator.compare);

console.log(words);
// Output: ['apple', 'Apple']

كائن الخيارات يحدد caseFirst: 'lower'، مما يتجاوز امتداد kf-upper في سلسلة اللغة. يستخدم المقارن ترتيب الأحرف الصغيرة أولاً.

التحقق من قيمة caseFirst التي يستخدمها المقارن

تُرجع طريقة resolvedOptions() الخيارات الفعلية التي يستخدمها المقارن، بما في ذلك إعداد caseFirst.

const collator = new Intl.Collator('en-US', { caseFirst: 'upper' });
const options = collator.resolvedOptions();

console.log(options.caseFirst);
// Output: "upper"

هذا مفيد لتصحيح الأخطاء أو التحقق من أن المقارن لديه التكوين المتوقع، خاصة عند دمج امتدادات Unicode مع كائنات الخيارات.

const collator = new Intl.Collator('en-US-u-kf-lower');
const options = collator.resolvedOptions();

console.log(options.caseFirst);
// Output: "lower"

تعكس الخيارات المحلولة إعداد امتداد Unicode عندما لا يتجاوزه كائن الخيارات.

متى تستخدم كل قيمة من قيم caseFirst

استخدم caseFirst: "upper" عندما:

  • تريد أن تظهر الأسماء المناسبة أو العناوين قبل الكلمات الشائعة
  • تتعامل اتفاقية تطبيقك مع النص المكتوب بأحرف كبيرة على أنه أكثر أهمية
  • تقوم بفرز الأسماء حيث تكون الإصدارات المكتوبة بأحرف كبيرة هي الأساسية

استخدم caseFirst: "lower" عندما:

  • تريد أن يظهر النص بأحرف صغيرة أولاً كشكل قياسي
  • تتعامل اتفاقية تطبيقك مع الأحرف الصغيرة كافتراضية والأحرف الكبيرة كخاصة
  • تقوم بفرز المعرفات التقنية حيث تكون الأحرف الصغيرة أكثر شيوعًا

استخدم caseFirst: "false" عندما:

  • تريد اتباع الاتفاقيات الخاصة باللغة المحلية
  • لا يهم ترتيب السلاسل المختلفة في الحالة لتطبيقك
  • تريد أن توضح صراحة أنك تستخدم الإعدادات الافتراضية بدلاً من حذف الخيار عن طريق الخطأ