Randomize ou Baralhe um Array em JavaScript
- Baralhar um array dependendo do motor JavaScript
- Medir a Aleatoriedade do Nosso Algoritmo Simples
-
Baralhar um array utilizando o algoritmo
Fisher-Yates
-
Baralhar um Array com a biblioteca
Underscore.js
ouLo-Dash
Neste tutorial, aprenderemos como baralhar ou randomizar um array em JavaScript; há muitas maneiras de baralhar um array em JavaScript - seja implementando algoritmos de baralhamento ou usando funções de baralhamento já existentes em algumas bibliotecas.
Baralhar um array é organizar o seu elemento aleatoriamente, por isso depende principalmente de como se reordena ou ordena o array com um grau de aleatoriedade.
Avancemos e descubramos diferentes formas de aleatorizar ou baralhar um array.
Baralhar um array dependendo do motor JavaScript
Comecemos por implementar um algoritmo simples de baralhamento do array, ordenando o array utilizando array.sort()
mas utilizando alguma aleatoriedade gerada pela equação Math.random() - 0.5
e -0.5
assegura que cada vez que chamamos o algoritmo, o valor aleatório pode ser positivo ou negativo.
Vamos implementar esse algoritmo simples com o poder do motor JavaScript e imprimir o shuffled Array para consola utilizando Console.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 a Aleatoriedade do Nosso Algoritmo Simples
A probabilidade das permutações dessa matriz pode ser calculada para verificar o quão excelente e aleatório o nosso algoritmo foi implementado.
Vamos ver como podemos medir a sua aleatoriedade.
- Criar um dicionário que irá contar a aparência de todas as permutações.
- Criar um laço que funcionará 1000000 vezes e cada vez aumentará a contagem da permutação formada
- Imprimir as contagens de todas as permutações possíveis e observar as probabilidades entre elas.
Este algoritmo de medição simples pode ser implementado como o seguinte:
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
A partir da saída acima, podemos ver claramente o viés como 135
, 315
, e 531
aparecem muito menos do que outros e contagens tão semelhantes umas às outras.
Baralhar um array utilizando o algoritmo Fisher-Yates
Este algoritmo simples baseado no motor JavaScript não é fiável na secção passada, mas um grande algoritmo chamado Fisher-Yates
é melhor no que diz respeito à sua eficiência e fiabilidade.
A ideia por detrás do algoritmo Fisher-Yates
é caminhar para a matriz em ordem inversa e trocar cada elemento com um aleatório antes dele. O Fisher-Yates
é um algoritmo simples mas muito eficiente e rápido.
Vamos implementar o 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);
Vamos então explicá-lo passo a passo:
for(var i =array.length-1 ; i>0 ;i--)
a para loop que andará sobre o array numa ordem inversa.Math.floor( Math.random() * (i + 1) )
Gerar um índice aleatório que varia entre 0 e i.[arr[i],arr[j]]=[arr[j],arr[i]]
está a trocar os elementosarr[i]
earr[j]
entre si utilizando a sintaxeDestructuring Assignment
.
Resultado:
(3) [3, 1, 5]
Agora vamos testar Fisher-Yates
o mesmo que fizemos 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
A partir da saída acima, podemos ver a grande diferença entre o algoritmo Fisher-Yates
e o algoritmo simples que implementámos antes e o quão fiável é o algoritmo Fisher-Yates
.
Baralhar um Array com a biblioteca Underscore.js
ou Lo-Dash
A famosa biblioteca Underscore.js
também fornece uma função de baralhamento que pode aleatorizar directamente um array sem a necessidade de escrever a sua implementação de qualquer algoritmo.
Vejamos o seguinte exemplo de utilização do método _.shuffle()
.
Primeiro, precisamos de importar a biblioteca utilizando o Cloudflare CDN
dentro do HTML Template,
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
Depois utilizamos o método _.shuffle()
como:
var tmpUnderscoreArray = [1, 3, 5];
resultArray = _.shuffle(tmpUnderscoreArray);
console.log(resultArray);
Resultado:
(3) [1, 5, 3]