Introducción
JavaScript es un lenguaje criticado por muchas personas, precisamente por sus métodos o maneras de hacer las cosas. Una de las cosas más criticadas es cómo ordenar arreglos en JavaScript.
Este lenguaje proporciona todo lo que necesitamos para ordenar arreglos, ya sean arreglos de cadenas, de enteros o incluso de objetos; porque nos permite definir una función de ordenamiento.
Pero bueno, vamos a ver algunos ejemplos para que quede claro. Ordenaremos en orden ascendente y descendente, arreglos de strings, de números y de objetos, usando el método sort.
Espero que después de este post no te queden dudas sobre cómo ordenar arrays. Cubriré los casos más comunes.
Finalmente quiero aclarar que esto funciona tanto en JavaScript del lado del navegador, como en JS del lado del servidor usando Node.JS.
Lecturas recomendadas
Te recomiendo leer sobre las funciones flecha, son una forma corta de escribir funciones anónimas; las mismas que usaremos para ordenar en los ejemplos.
Sobre esta función
Cuidado al usar esta función. Debemos leer la documentación antes, y es que el método sort en JavaScript para ordenar arreglos no devuelve nada, sino que modifica al arreglo internamente.
Es decir, al llamarla no regresa un nuevo arreglo, sino que modifica al que le aplicamos el método. Quiero que esto quede claro antes de que sigamos con los ejemplos.
Ejemplo básico de sort en JavaScript para ordenar arreglos
No vamos a meternos en ejemplos complejos. Veamos cómo ordenar un arreglo de números:
const arreglo = [1, 2, 50,10];
console.log("Antes de ordenar: ", arreglo);
arreglo.sort();
console.log("Después de ordenar: ", arreglo);
La salida es:
Antes de ordenar: [ 1, 2, 50, 10 ]
Después de ordenar: [ 1, 10, 2, 50 ]
Y justo aquí viene lo complicado. No, no estoy equivocado, realmente esa fue la salida. ¿Por qué puso el 10 antes del 2? la respuesta viene en el siguiente apartado, y es que por defecto sort ordenará a los elementos como si fueran cadenas. Ordenando alfabéticamente, el orden es correcto.
Comportamiento por defecto de sort
Por defecto, sort ordena a los elementos como si de cadenas o strings se tratara. Si estamos ordenando cadenas, entonces no tenemos que proporcionar función de ordenamiento. Veamos este ejemplo de un arreglo de nombres:
const arreglo = ["María", "Luis", "Alberto", "Maggie"];
console.log("Antes de ordenar: ", arreglo);
arreglo.sort();
console.log("Después de ordenar: ", arreglo);
La salida es:
Antes de ordenar: [ ‘María’, ‘Luis’, ‘Alberto’, ‘Maggie’ ]
Después de ordenar: [ ‘Alberto’, ‘Luis’, ‘Maggie’, ‘María’ ]
Eso es correcto, pues son cadenas. Veamos ahora cómo ordenar otro tipo de arreglos.
Ordenar arreglo de enteros ascendente
Aquí viene algo bueno y es la función que le podemos pasar como argumento a sort. Básicamente esta función le dice a sort cómo ordenar los datos; en dicho método debemos regresar un 0, un número negativo o uno positivo.
Es importante destacar que esta función será llamada con dos argumentos, que representan a los dos elementos que van a ser comparados para saber si uno va antes del otro.
¿Y cómo hacemos esto? bueno, regresamos el resultado de una resta. Digamos que vamos a comparar a 10 y 50. Regresamos 10 – 50, que es -40, el cual es un número negativo, así sabrá que el 10 va antes del 50.
En caso de que quisiéramos un orden inverso (descendente en este caso), regresaríamos 50 – 10, lo que regresaría el 40 positivo y pondría al 10 después del 50.
Finalmente, si ambos elementos son iguales (por ejemplo, si se comparasen 10 y 10) el resultado sería 0 y pondría a los elementos juntos, sin importar el orden.
Código de ejemplo
Pero bueno, basta de explicaciones. Veamos un ejemplo de código.
const arreglo = [20, 50, 10, 1, 80, 20, 80, 60];
console.log("Antes de ordenar: ", arreglo);
arreglo.sort((unNumero, otroNumero) => unNumero - otroNumero);
console.log("Después de ordenar: ", arreglo);
Aquí vemos a una función flecha. Nos pasan un número y otro número; los cuales serán comparados. Y regresamos el resultado de unNumero - otroNumero
, lo que hará que el arreglo sea ordenado en forma ascendente; es decir, de menor a mayor.
La salida es:
Antes de ordenar: [ 20, 50, 10, 1, 80, 20, 80, 60 ]
Después de ordenar: [ 1, 10, 20, 20, 50, 60, 80, 80 ]
Ahora sí todo es correcto.
Arreglo de enteros ordenado de forma descendente
Es casi la misma función que arriba, pero ahora invertimos los operandos o como se llame a los números que se restan. Queda así:
const arreglo = [20, 50, 10, 1, 80, 20, 80, 60];
console.log("Antes de ordenar: ", arreglo);
arreglo.sort((unNumero, otroNumero) => otroNumero - unNumero);
console.log("Después de ordenar: ", arreglo);
Como vemos, en lugar de hacer unNumero - otroNumero
, restamos de forma que regrese el resultado de otroNumero - unNumero
. Así se ordena en orden descendente; es decir, del más grande al más pequeño.
He aquí la salida:
Antes de ordenar: [ 20, 50, 10, 1, 80, 20, 80, 60 ]
Después de ordenar: [ 80, 80, 60, 50, 20, 20, 10, 1 ]
Tenemos a nuestro arreglo de números ordenado de forma descendente.
Nota: este método y el de arriba también funciona para arreglos de flotantes.
Usar sort para ordenar un arreglo de strings de forma ascendente
Bueno, esa es la forma por la que se ordena un arreglo si no indicamos función. Así que si queremos ordenar un arreglo de forma ascendente, y ese arreglo tiene cadenas, no hace falta más que llamar a arreglo.sort()
como se vio en el ejemplo de arriba.
En otras palabras, no le pasamos argumentos a sort, pues si no le indicamos el orden, ordenará como si fueran cadenas en orden ascendente.
Ordenar strings en un arreglo de manera descendente
Con reverse
Aquí tenemos dos opciones fáciles. La primera y más fácil, pero no creo que sea la más eficiente, es llamar a arreglo.sort()
y luego llamar a arreglo.reverse()
. Así como se ve en el siguiente código:
// Ahora no es constante porque cambiaremos su valor más tarde
let arreglo = ["Hola", "Animales fantásticos", "Elefante", "Berenjena", "Uno"];
console.log("Antes de ordenar: ", arreglo);
arreglo.sort();
// Justo aquí lo invertimos
arreglo = arreglo.reverse();
console.log("Después de ordenar: ", arreglo);
La salida es:
Antes de ordenar: [ ‘Hola’, ‘Animales fantásticos’, ‘Elefante’, ‘Berenjena’, ‘Uno’ ]
Después de ordenar: [ ‘Uno’, ‘Hola’, ‘Elefante’, ‘Berenjena’, ‘Animales fantásticos’ ]
Primero lo ordenamos con el método por defecto, después lo volteamos. Fácil y sencillo.
Comparando cadenas usando localeCompare
Existe otra forma, y es comparando las cadenas de tal manera que sea como hacer restas.
const arreglo = ["Hola", "Animales fantásticos", "Elefante", "Berenjena", "Uno"];
console.log("Antes de ordenar: ", arreglo);
arreglo.sort((unaCadena, otraCadena) => otraCadena.localeCompare(unaCadena));
console.log("Después de ordenar: ", arreglo);
Ahora usamos el método localeCompare que compara dos cadenas y devuelve un 1, un 0 o un -1 dependiendo de si la cadena va antes, es igual o va después que la otra. Casi como cuando lo hacíamos con números.
La salida es:
Antes de ordenar: [ ‘Hola’, ‘Animales fantásticos’, ‘Elefante’, ‘Berenjena’, ‘Uno’ ]
Después de ordenar: [ ‘Uno’, ‘Hola’, ‘Elefante’, ‘Berenjena’, ‘Animales fantásticos’ ]
Así es como ordenamos arreglos de cadenas en forma descendente.
Ordenar arreglo de objetos en JavaScript
Para terminar este post veamos cómo podemos arreglar un arreglo de objetos. Obviamente no compararemos objetos, compararemos propiedades de objetos.
Por ejemplo, tenemos este arreglo de mascotas:
const arreglo = [
{
"nombre": "Maggie",
"edad": 5,
}, {
"nombre": "Cuco",
"edad": 1
},
{
"nombre": "Misifú",
"edad": 10
},
{
"nombre": "Teddy",
"edad": 2
}
];
Ahora digamos que vamos a ordenarlas por edad. Para ello simplemente comparamos edad con la edad de la otra mascota, y regresamos el resultado de la resta, como cuando trabajamos con enteros.
Así:
const arreglo = [
{
"nombre": "Maggie",
"edad": 5,
}, {
"nombre": "Cuco",
"edad": 1
},
{
"nombre": "Misifú",
"edad": 10
},
{
"nombre": "Teddy",
"edad": 2
}
];
console.log("Antes de ordenar: ", arreglo);
arreglo.sort((unaMascota, otraMascota) => unaMascota.edad - otraMascota.edad);
console.log("Después de ordenar: ", arreglo);
En este caso lo que hacemos es comparar la propiedad de un objeto que recibimos en la función. La salida es:
Antes de ordenar: [ { nombre: ‘Maggie’, edad: 5 },
{ nombre: ‘Cuco’, edad: 1 },
{ nombre: ‘Misifú’, edad: 10 },
{ nombre: ‘Teddy’, edad: 2 } ]
Después de ordenar: [ { nombre: ‘Cuco’, edad: 1 },
{ nombre: ‘Teddy’, edad: 2 },
{ nombre: ‘Maggie’, edad: 5 },
{ nombre: ‘Misifú’, edad: 10 } ]
Las ha ordenado correctamente. Si fuera por edad, pero ascendente, sería así:
arreglo.sort((unaMascota, otraMascota) => otraMascota.edad - unaMascota.edad);
Y si quisiéramos que fueran ordenadas por nombre, usamos localeCompare. Si seguimos este código, ordenará a las mascotas según su nombre, en forma ascendente:
arreglo.sort((unaMascota, otraMascota) => unaMascota.nombre.localeCompare(otraMascota.nombre));
Para no dejar huecos, si queremos que sean ordenadas por nombre pero en forma descendente, sería así:
arreglo.sort((unaMascota, otraMascota) => otraMascota.nombre.localeCompare(unaMascota.nombre));
Conclusión
Así es como podemos ordenar todo tipo de arreglos en JavaScript. Y no es que sea difícil, sino que a veces no hay suficiente documentación o pensamos que es cosa del otro mundo.
Me parece que cubrí los casos más comunes, y si no, puedes escribir un comentario. Por cierto, aquí dejo un enlace a la documentación oficial o más bien a la documentación de MDN.