Ordenamiento de arreglos unidimensionales de strings con JavaScript
Tags: javascript, webdev, html, spanish
Published: 2020-06-15 14:49:12

Existen métodos nativos muy útiles en las diferentes especificaciones de JavaScript, uno de ellos es el método `sort()` perteneciente a ES1. 

`sort()` **es un método que se aplica a vectores.** Nos permite ordenar un array unidimensional de strings (por orden alfabético), aunque con alguna lógica extra se puede usar para ordenar arrays numéricos.

## **Sintaxis básica**

```javascript
array.sort(funciónDeComparación);
```

Donde:
* `array` es el nombre del arreglo el cual se desea ordenar.
* `sort()` es el método como tal.
* `funciónDeComparación` es una función parámetro opcional que se usa para ordenamientos un tanto más complejos.

## **Características importantes**
Se debe tener en cuenta los siguientes puntos:
* `sort()` por defecto ordena arrays de strings en orden alfabético de manera ascendente. 
* `sort()` **modifica el array original** , por lo que para mantener la inmutabilidad del array será necesario hacer una copia del mismo antes de aplicar el método.
* Resultados inesperados con letras acentuadas. 
* Resultados inesperados con mayúsculas y minúsculas (por ejemplo: `Ana != ana`)

## **Ordenar un array ascendientemente (de la A a la Z)**

Supongamos que tenemos un array de nombres como el siguiente:

```javascript
let nombres = ["Carlos", "Juan", "Ana", "Gabriela", "Pedro"];
```

Para ordenarlo de manera ascendiente bastaría con hacer lo siguiente: 

```javascript
let orderArrayStringsAsc = array => array.sort();
console.log(orderArrayStringsAsc(nombres));
//salida: ["Ana", "Carlos", "Gabriela", "Juan", "Pedro"]
```


## **Ordenar un array descendientemente (de la Z a la A)**
Para ordenar el array de nombres anterior bastará con encadenar `reverse()` a `sort()` de la siguiente manera: 

```javascript
let orderArrayStringsDesc = array => array.sort().reverse();
console.log(orderArrayStringsDesc(nombres));
//salida: ["Pedro", "Juan", "Gabriela", "Carlos", "Ana"]
```

## **Resultados Inesperados** :warning:
### **sort() y Case Sensitive** 
Imaginemos que ahora tenemos un array de países como el siguiente:

```javascript
let paises = ["bolivia", "Argentina", "Portugal", "España", "Francia"];
```

Aplicando el método `sort()` de manera ascendente esperaríamos una salida como la siguiente:

```javascript
["Argentina", "bolivia", "España", "Francia", "Portugal"];
```

¡Pero vaya sorpresa! La consola nos retorna la siguiente salida: 

```javascript
["Argentina", "España", "Francia", "Portugal", "bolivia"];
```

![wft](https://media.giphy.com/media/xL7PDV9frcudO/giphy.gif)

¿Qué paso acá? Esto puede ser algo desconcertante al principio pero en realidad es muy sencillo de explicar.
`sort()` ordena sus elementos en base al código ASCII de la primera letra de sus items, por ejemplo, el primer elemento de nuestro array de países es `'Argentina'`, entonces se toma su primera letra y se convierte a ASCII, por tanto, tendríamos `A = 65`, bajo esta lógica tenemos la siguiente tabla: 


| Items     |  Primera letra de cada item  |  Código ASCII |
|---------- |:-----------------------------|---------------|
| bolivia   | b                            |    98         |
| Argentina | A                            |    65         |
| Portugal  | P                            |    80         |
| España    | E                            |    69         |
| Francia   | F                            |    70         |

> Puedes consultar una tabla completa de [código ASCII](https://elcodigoascii.com.ar/) acá. 

Por ende, el equivalente en código ASCII de nuestro array de países se vería de la siguiente manera:

```javascript
let paises = ["bolivia", "Argentina", "Portugal", "España", "Francia"];
let paisesASCII = [98,65,80,69,70];
```

Aplicando `sort()` al array paisesASCII comprendemos por qué sucede este extraño comportamiento, las letras minúsculas en ASCII tienen valores numéricos más altos, por ello, al intentar ordenar el array países `bolivia` se sitúa hasta el final. 

¿Cómo solucionamos este pequeño inconveniente? La clave está en el parámetro opcional de `sort()` :sunglasses:

`sort()` recibe una función que, a su vez, recibe 2 parámetros (`a` y `b`) 
El método se encargará de comparar ambos valores y debe:
* Devolver un valor positivo (1) si el primer valor es superior al segundo
* Devolver un valor negativo (-1) si el primer valor es inferior al segundo
* Devolver un valor cero (0) si los dos valores son iguales o equivalentes para la ordenación.

El ejemplo se corregido se vería de la siguiente manera: 
```javascript
let paises = ["bolivia", "Argentina", "Portugal", "España", "Francia"];

let orderArrayStringsAsc = array => array.sort((a, b) =>
  a.toLowerCase() > b.toLowerCase() ? 1 :
  a.toLowerCase() < b.toLowerCase() ? -1:
  0);
console.log(orderArrayStringsAsc(paises));
//salida: ["Argentina", "bolivia", "España", "Francia", "Portugal"]
```
### **sort() vs tildes**
Resultados inesperados se obtendrán al intentar ordenar arrays cuyos elementos empiecen por tildes, una solución extremadamente simple y funcional es usar el método `localeCompare()` perteneciente a la especificación ES1 de javascript. 
A grandes rasgos, `localeCompare()` funciona de manera muy similar a la función parámetro opcional de `sort()` tomando en cuenta cualquier símbolo especial (como acentos `´` o diéresis  `¨`)
En el siguiente ejemplo se puede observar mejor el funcionamiento de `sort()` combinado con `localeCompare()`:

```javascript
let prefesiones = ["Ingeniero", "Cantante", "Doctor", "árbitro", "Policia"];

let orderArrayStringsAsc = array => array.sort((a, b) => a.localeCompare(b))
console.log(orderArrayStringsAsc(prefesiones));
//salida: ["árbitro", "Cantante", "Doctor", "Ingeniero", "Policia"]
```

## **Referencias** :link:
* https://www.w3schools.com/jsref/jsref_sort.asp
* https://www.w3schools.com/js/js_array_sort.asp
* https://www.todojs.com/usar-correctamente-el-metodo-sort/

---

## **Conclusiones** :heavy_check_mark:
Después de comprender un poco mejor el funcionamiento de `sort()` en javascript se pueden llegar a las siguientes conclusiones: 
* `sort()` se aplica a **arrays unidimensionales o vectores**.
* Recibe una función parámetro opcional muy útil para ordenamientos más precisos.
* Por defecto ordena arrays de strings en orden alfabético de manera ascendente. 
* **Modifica el array original** por lo que carece de **inmutabilidad** de datos.
* Es case sensitive con los items de los arreglos.

Para finalizar, me parece menester recalcar la importancia de comprender el funcionamiento interno de este método como de cualquier otro, considero obligación del desarrollador preguntarse siempre el funcionamiento de las cosas evitando usarlas sin antes tratar de entenderlas.