Cómo controlar si las mayúsculas o minúsculas aparecen primero en la ordenación
Utiliza la opción caseFirst en Intl.Collator para determinar el orden de las mayúsculas y minúsculas al ordenar cadenas de texto
Introducción
Cuando ordenas un array de cadenas que solo difieren en su capitalización, JavaScript necesita decidir qué versión va primero. ¿Debería apple ir antes que Apple, o debería Apple ir antes que apple? Diferentes aplicaciones tienen diferentes requisitos para este ordenamiento.
Por defecto, el orden de clasificación para cadenas que solo difieren en mayúsculas y minúsculas depende de la configuración de localización y sensibilidad. En muchos casos, cadenas como apple y Apple se tratan como iguales, haciendo que su orden sea impredecible. Cuando el orden de mayúsculas y minúsculas es importante para tu aplicación, necesitas un control explícito sobre si las letras mayúsculas o minúsculas se ordenan primero.
La API Intl.Collator proporciona una opción caseFirst que determina el orden de mayúsculas y minúsculas. Puedes configurar el comparador para colocar letras mayúsculas antes que las minúsculas, letras minúsculas antes que las mayúsculas, o usar el comportamiento predeterminado de la localización. Esta lección explica cómo funciona la opción caseFirst, cuándo tiene efecto y cómo usarla en escenarios prácticos de ordenamiento.
Qué hace la opción caseFirst
La opción caseFirst controla el orden de las cadenas que difieren solo en su capitalización. Acepta tres valores de cadena: "upper", "lower", o "false".
Cuando se establece en "upper", las letras mayúsculas se ordenan antes que sus equivalentes en minúsculas. La cadena Apple viene antes que apple.
Cuando se establece en "lower", las letras minúsculas se ordenan antes que sus equivalentes en mayúsculas. La cadena apple viene antes que Apple.
Cuando se establece en "false" (el valor de cadena, no el booleano), el comparador utiliza el orden de mayúsculas y minúsculas predeterminado de la localización. Este es el comportamiento predeterminado cuando no especificas la opción.
La opción caseFirst solo afecta a las cadenas que son idénticas excepto por las mayúsculas y minúsculas. Las cadenas que difieren en sus letras base se ordenan según las reglas alfabéticas normales independientemente de esta configuración.
Cómo funciona el ordenamiento de casos por defecto
Sin especificar la opción caseFirst, el comparador utiliza un comportamiento predeterminado que depende de la configuración de la localización y sensibilidad.
const collator = new Intl.Collator('en-US');
const words = ['apple', 'Apple', 'APPLE'];
words.sort(collator.compare);
console.log(words);
// Resultado: ['apple', 'Apple', 'APPLE']
El orden de salida depende de la implementación y la localización. Con la configuración de sensibilidad predeterminada, el comparador considera las diferencias de mayúsculas y minúsculas, pero el orden específico de apple, Apple y APPLE varía.
Diferentes localizaciones tienen diferentes convenciones de ordenamiento de casos por defecto. Algunas localizaciones tradicionalmente colocan las letras minúsculas primero, mientras que otras colocan las letras mayúsculas primero. Depender del comportamiento predeterminado produce resultados inconsistentes en diferentes entornos.
Colocando letras mayúsculas primero con caseFirst upper
Establecer caseFirst: "upper" asegura que las letras mayúsculas siempre aparezcan antes que sus equivalentes en minúsculas en los resultados ordenados.
const collator = new Intl.Collator('en-US', { caseFirst: 'upper' });
const words = ['apple', 'Apple', 'banana', 'Banana'];
words.sort(collator.compare);
console.log(words);
// Resultado: ['Apple', 'apple', 'Banana', 'banana']
El comparador ordena alfabéticamente por la letra base primero, luego aplica el ordenamiento de casos dentro de cada grupo. Entre las palabras que comienzan con a, Apple viene antes que apple. Entre las palabras que comienzan con b, Banana viene antes que banana.
Este ordenamiento es útil cuando se muestran listas donde los nombres propios o títulos en mayúsculas deben aparecer prominentemente antes que los nombres comunes.
const collator = new Intl.Collator('en-US', { caseFirst: 'upper' });
const names = ['smith', 'Smith', 'jones', 'Jones'];
names.sort(collator.compare);
console.log(names);
// Resultado: ['Jones', 'jones', 'Smith', 'smith']
Los nombres en mayúsculas aparecen antes que las versiones en minúsculas, lo que facilita distinguir los nombres propios de las palabras comunes en listas mixtas.
Colocando letras minúsculas primero con caseFirst lower
Establecer caseFirst: "lower" asegura que las letras minúsculas siempre aparezcan antes que sus equivalentes en mayúsculas en los resultados ordenados.
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']
El comparador ordena alfabéticamente primero, luego coloca las versiones en minúsculas antes que las versiones en mayúsculas dentro de cada grupo alfabético.
Este ordenamiento coincide con las convenciones donde el texto en minúsculas se considera más estándar o neutral, reservando las mayúsculas para énfasis o casos especiales.
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']
Las etiquetas en minúsculas aparecen primero, lo que es útil cuando las minúsculas representan la forma canónica y las versiones en mayúsculas son variaciones menos comunes.
Usando caseFirst false para el comportamiento predeterminado del locale
Establecer caseFirst: "false" (el valor de cadena) solicita explícitamente el ordenamiento de casos predeterminado del locale. Esto produce el mismo resultado que omitir la opción por completo.
const collator = new Intl.Collator('en-US', { caseFirst: 'false' });
const words = ['apple', 'Apple', 'APPLE'];
words.sort(collator.compare);
console.log(words);
// El resultado depende de la implementación del locale
El orden de salida depende de lo que el locale considere estándar. Algunos locales definen primero las mayúsculas, otros definen primero las minúsculas, y algunos tratan las cadenas con diferencias de caso como iguales.
Esta opción es útil cuando quieres hacer explícito que estás utilizando los valores predeterminados del locale en lugar de omitir accidentalmente una opción de configuración.
Cuando caseFirst no tiene efecto
La opción caseFirst solo afecta la comparación cuando la configuración de sensibilidad permite que las diferencias de caso sean relevantes. Con sensitivity: "base" o sensitivity: "accent", las diferencias de caso se ignoran por completo, haciendo que la opción caseFirst sea irrelevante.
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'] (o cualquier orden)
Con sensibilidad base, el comparador trata las tres cadenas como iguales. La opción caseFirst no tiene efecto porque el caso no se considera en absoluto. El algoritmo de ordenación preserva el orden original de elementos iguales (ordenación estable), por lo que la salida coincide con el orden de entrada.
Para que caseFirst tenga efecto, usa sensitivity: "case" o sensitivity: "variant" (el predeterminado).
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']
Con sensibilidad variante (que considera todas las diferencias, incluido el caso), la opción caseFirst determina el orden de estas cadenas con variaciones de caso.
Ordenar nombres con un orden de mayúsculas y minúsculas consistente
Al ordenar nombres de usuario u otros nombres propios, un orden consistente de mayúsculas y minúsculas garantiza resultados predecibles en toda la aplicación.
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);
});
// Output:
// Alice
// alice
// Bob
// bob
El comparador coloca los nombres en mayúsculas antes de las versiones en minúsculas. Este ordenamiento facilita la visualización de nombres propios frente a palabras comunes en conjuntos de datos mixtos.
Ordenar nombres de archivos con un orden de mayúsculas y minúsculas controlado
Los sistemas de archivos tienen diferentes comportamientos de sensibilidad a mayúsculas y minúsculas. Algunos tratan las mayúsculas y minúsculas como iguales, otros las tratan como diferentes. El ordenamiento explícito de mayúsculas y minúsculas asegura que tus listas de archivos ordenadas coincidan con las expectativas del usuario independientemente del sistema de archivos subyacente.
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);
// Output: ['index.js', 'Index.js', 'readme.md', 'README.md']
Las versiones en minúsculas aparecen primero, coincidiendo con la convención donde los nombres de archivos en minúsculas son más estándar en sistemas tipo Unix.
Combinando caseFirst con ordenación numérica
La opción caseFirst funciona junto con otras opciones de ordenación como numeric. Puedes ordenar cadenas con números incrustados mientras controlas el orden de mayúsculas y minúsculas.
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);
// Output: ['Item1', 'item1', 'Item2', 'item2', 'Item10', 'item10']
El comparador aplica la comparación numérica para las partes numéricas y el orden de mayúsculas y minúsculas para las partes de letras. Los elementos se ordenan primero por valor numérico (1, 2, 10), luego por mayúsculas y minúsculas dentro de cada grupo numérico.
Uso de la clave de extensión Unicode para caseFirst
La opción caseFirst también se puede establecer a través de una extensión Unicode en el identificador de configuración regional utilizando la clave kf. Los valores de extensión son upper, lower y false.
const collator = new Intl.Collator('en-US-u-kf-upper');
const words = ['apple', 'Apple', 'banana', 'Banana'];
words.sort(collator.compare);
console.log(words);
// Salida: ['Apple', 'apple', 'Banana', 'banana']
La cadena de configuración regional en-US-u-kf-upper especifica inglés estadounidense con ordenación de mayúsculas primero. Esto produce el mismo resultado que pasar { caseFirst: 'upper' } en el objeto de opciones.
Cuando tanto la extensión Unicode como el objeto de opciones especifican caseFirst, el objeto de opciones tiene prioridad.
const collator = new Intl.Collator('en-US-u-kf-upper', {
caseFirst: 'lower'
});
const words = ['apple', 'Apple'];
words.sort(collator.compare);
console.log(words);
// Salida: ['apple', 'Apple']
El objeto de opciones especifica caseFirst: 'lower', lo que anula la extensión kf-upper en la cadena de configuración regional. El comparador utiliza ordenación de minúsculas primero.
Verificación del valor caseFirst que está utilizando un comparador
El método resolvedOptions() devuelve las opciones reales que el comparador está utilizando, incluida la configuración caseFirst.
const collator = new Intl.Collator('en-US', { caseFirst: 'upper' });
const options = collator.resolvedOptions();
console.log(options.caseFirst);
// Salida: "upper"
Esto es útil para depurar o verificar que tu comparador tiene la configuración esperada, especialmente cuando se combinan extensiones Unicode con objetos de opciones.
const collator = new Intl.Collator('en-US-u-kf-lower');
const options = collator.resolvedOptions();
console.log(options.caseFirst);
// Salida: "lower"
Las opciones resueltas reflejan la configuración de extensión Unicode cuando ningún objeto de opciones la anula.
Cuándo usar cada valor de caseFirst
Usa caseFirst: "upper" cuando:
- Quieres que los nombres propios o títulos aparezcan antes que las palabras comunes
- La convención de tu aplicación trata el texto en mayúsculas como más significativo
- Estás ordenando nombres donde las versiones en mayúsculas son canónicas
Usa caseFirst: "lower" cuando:
- Quieres que el texto en minúsculas aparezca primero como forma estándar
- La convención de tu aplicación trata las minúsculas como predeterminadas y las mayúsculas como especiales
- Estás ordenando identificadores técnicos donde las minúsculas son más comunes
Usa caseFirst: "false" cuando:
- Quieres seguir las convenciones específicas de la configuración regional
- El orden de las cadenas que difieren en mayúsculas y minúsculas no es importante para tu aplicación
- Quieres dejar explícito que estás utilizando valores predeterminados en lugar de omitir accidentalmente la opción