Cómo aleatorizar o mezclar un array en JavaScript

Moataz Farid 12 octubre 2023
  1. Barajar un array dependiendo del motor de JavaScript
  2. Medir la aleatoriedad de nuestro simple algoritmo
  3. Barajar un array usando el algoritmo de barajado Fisher-Yates
  4. Barajar un array con la biblioteca Underscore.js o Lo-Dash
Cómo aleatorizar o mezclar un array en JavaScript

En este tutorial, aprenderemos cómo barajar o aleatorizar un array en JavaScript; hay muchas maneras de barajar un array en JavaScript, ya sea implementando algoritmos de barajado o usando funciones de barajado ya existentes en algunas bibliotecas.

Barajar un array es organizar su elemento de forma aleatoria, por lo que depende principalmente de cómo se reordena u ordena el array con un grado de aleatoriedad.

Avancemos y descubramos diferentes formas de aleatorizar o barajar un conjunto.

Barajar un array dependiendo del motor de JavaScript

Comencemos con la implementación de un simple algoritmo de barajado de matrices ordenando el array usando array.sort() pero usando algo de aleatoriedad generada por la ecuación Math.random() - 0.5 y -0.5 asegura que cada vez que llamamos al algoritmo, el valor de aleatoriedad puede ser positivo o negativo.

Implementamos ese simple algoritmo con la potencia del motor de JavaScript e imprimimos el Array barajado a la consola usando consola.log():

function shuffleArray(inputArray) {
  inputArray.sort(() => Math.random() - 0.5);
}

var demoArray = [1, 3, 5];
shuffleArray(demoArray);
console.log(demoArray);

Resultado:

[1, 5, 3]

Medir la aleatoriedad de nuestro simple algoritmo

La probabilidad de las permutaciones de ese array puede ser calculada para comprobar cuán excelente y aleatorio es nuestro algoritmo que hemos implementado.

Veamos cómo podemos medir su aleatoriedad.

  1. Crear un diccionario que cuente la apariencia de todas las permutaciones.
  2. Crear un bucle que se ejecutará 1000000 veces y cada vez aumentará la cuenta de la permutación formada
  3. Imprime los recuentos de todas las permutaciones posibles y observa las probabilidades entre ellas.

Este simple algoritmo de medición puede ser implementado como el siguiente:

function shuffleArray(inputArray) {
  inputArray.sort(() => Math.random() - 0.5);
}

// counts of the appearances for all possible permutations
var countDic = {
  '153': 0,
  '135': 0,
  '315': 0,
  '351': 0,
  '531': 0,
  '513': 0,
};

// Creating the loop
for (var i = 0; i < 1000000; i++) {
  var arr = [1, 5, 3];
  shuffleArray(arr);
  countDic[arr.join('')]++;
}

// Print the counts of all possible permutations
for (var key in countDic) {
  console.log(`${key}: ${countDic[key]}`);
}

Resultado:

135: 62256
153: 375832
315: 62976
351: 311865
513: 124518
531: 62553

De la salida anterior, podemos ver claramente el sesgo como 135, 315 y 531 aparecen mucho menos que otros y por lo tanto los conteos son similares entre sí.

Barajar un array usando el algoritmo de barajado Fisher-Yates

Este simple algoritmo basado en el motor de JavaScript no es fiable en la sección anterior, pero un gran algoritmo llamado Fisher-Yates es mejor en cuanto a su eficiencia y fiabilidad.

La idea detrás del algoritmo Fisher-Yates es caminar hacia el array en orden inverso e intercambiar cada elemento con uno al azar antes de él. Fisher-Yates es un algoritmo simple pero muy eficiente y rápido.

Vamos a implementar el algoritmo Fisher-Yates:

function fisherYatesShuffle(arr) {
  for (var i = arr.length - 1; i > 0; i--) {
    var j = Math.floor(Math.random() * (i + 1));  // random index
    [arr[i], arr[j]] = [arr[j], arr[i]];          // swap
  }
}

var tmpArray = [1, 3, 5];
fisherYatesShuffle(tmpArray);
console.log(tmpArray);

Así que vamos a explicarlo paso a paso:

  1. for(var i =array.length-1 ; i>0 ;i--) a for loop que caminará sobre el array en orden inverso.
  2. Math.floor( Math.random() * (i + 1) ) Generando un índice aleatorio que va de 0 a i.
  3. [arr[i],arr[j]]=[arr[j],arr[i]] está intercambiando los elementos arr[i] y arr[j] entre sí usando la sintaxis de la sintaxis de asignación.

Resultado:

(3) [3, 1, 5]

Ahora vamos a probar Fisher-Yates lo mismo que hicimos antes:

// counts of the appearances for all possible permutations
var countDic = {
  '153': 0,
  '135': 0,
  '315': 0,
  '351': 0,
  '531': 0,
  '513': 0,
};

// Creating the loop
for (var i = 0; i < 1000000; i++) {
  var arr = [1, 5, 3];
  fisherYatesShuffle(arr);
  countDic[arr.join('')]++;
}

// Print the counts of all possible permutations
for (var key in countDic) {
  console.log(`${key}: ${countDic[key]}`);
}

Resultado:

135: 166734
153: 166578
315: 166908
351: 166832
513: 166535
531: 166413

De la salida anterior, se puede ver la gran diferencia entre el algoritmo de Fisher-Yates y el simple algoritmo que implementamos antes y lo fiable que es el algoritmo de Fisher-Yates.

Barajar un array con la biblioteca Underscore.js o Lo-Dash

La famosa librería Underscore.js también proporciona una función de barajado que puede aleatorizar directamente un array sin necesidad de escribir su implementación de ningún algoritmo.

Veamos el siguiente ejemplo de uso del método _.shuffle().

Primero, necesitamos importar la librería usando el Cloudflare CDN dentro de la plantilla HTML,

<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>

Entonces usamos el método _.shuffle() como:

var tmpUnderscoreArray = [1, 3, 5];
resultArray = _.shuffle(tmpUnderscoreArray);
console.log(resultArray);

Resultado:

(3) [1, 5, 3]

Artículo relacionado - JavaScript Array