JavaScript에서 배열 무작위 화 또는 셔플
- JavaScript 엔진에 따라 배열 섞기
- 간단한 알고리즘의 무작위성 측정
-
Fisher-Yates
셔플 알고리즘을 사용하여 배열 셔플 -
Underscore.js
또는Lo-Dash
라이브러리로 배열 셔플
이 튜토리얼에서는 JavaScript에서 배열을 섞거나 무작위 화하는 방법을 배웁니다. 셔플 링 알고리즘을 구현하거나 일부 라이브러리에 이미 존재하는 셔플 함수를 사용하여 JavaScript에서 배열을 셔플하는 방법에는 여러 가지가 있습니다.
배열을 섞는 것은 요소를 무작위로 배열하는 것이므로 주로 임의의 정도를 사용하여 배열을 재정렬하거나 정렬하는 방법에 따라 다릅니다.
앞으로 나아가서 배열을 무작위 화하거나 섞는 다양한 방법을 찾아 보겠습니다.
JavaScript 엔진에 따라 배열 섞기
array.sort()
를 사용하여 배열을 정렬하여 간단한 배열 셔플 링 알고리즘을 구현하는 것으로 시작하겠습니다. 그러나 방정식Math.random() - 0.5
및-0.5
에 의해 생성 된 임의성을 사용하면 다음을 호출 할 때마다 알고리즘에서 임의의 값은 양수 또는 음수 일 수 있습니다.
JavaScript 엔진의 힘으로 간단한 알고리즘을 구현하고Console.log()
를 사용하여 섞인 배열을 콘솔에 인쇄 해 보겠습니다.
function shuffleArray(inputArray) {
inputArray.sort(() => Math.random() - 0.5);
}
var demoArray = [1, 3, 5];
shuffleArray(demoArray);
console.log(demoArray);
출력:
[1, 5, 3]
간단한 알고리즘의 무작위성 측정
해당 배열의 순열 확률을 계산하여 우리가 구현 한 알고리즘이 얼마나 우수하고 무작위인지 확인할 수 있습니다.
임의성을 측정하는 방법을 살펴 보겠습니다.
- 모든 순열의 모양을 계산할 사전을 만듭니다.
- 1000000 번 실행되는 루프를 생성하고 매번 형성된 순열의 수를 증가시킵니다.
- 가능한 모든 순열의 수를 인쇄하고 그 사이의 확률을 관찰합니다.
이 간단한 측정 알고리즘은 다음과 같이 구현할 수 있습니다.
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]}`);
}
출력:
135: 62256
153: 375832
315: 62976
351: 311865
513: 124518
531: 62553
위의 출력에서 우리는 135
, 315
, 531
이 다른 것보다 훨씬 적게 나타나고 서로 비슷한 수로 편향을 명확하게 볼 수 있습니다.
Fisher-Yates
셔플 알고리즘을 사용하여 배열 셔플
JavaScript 엔진을 기반으로 한이 간단한 알고리즘은 이전 섹션에서는 신뢰할 수 없었지만 Fisher-Yates
라는 훌륭한 알고리즘이 효율성과 신뢰성 측면에서 더 좋습니다.
Fisher-Yates
알고리즘의 기본 개념은 배열을 역순으로 걸어 가서 각 요소를 임의의 요소로 교체하는 것입니다. Fisher-Yates
는 간단하지만 매우 효율적이고 빠른 알고리즘입니다.
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);
그래서 단계별로 설명해 봅시다.
for(var i =array.length-1 ; i>0 ;i--)
배열에서 역순으로 걸을 for 루프.Math.floor( Math.random() * (i + 1) )
0과 i 사이의 임의 인덱스 생성.[arr[i],arr[j]]=[arr[j],arr[i]]
는arr[i]
와arr[j]
요소를Destructuring Assignment
구문.
출력:
(3) [3, 1, 5]
이제 이전과 동일한 방식으로Fisher-Yates
를 테스트 해 보겠습니다.
// 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]}`);
}
출력:
135: 166734
153: 166578
315: 166908
351: 166832
513: 166535
531: 166413
위의 출력에서 Fisher-Yates
알고리즘과 이전에 구현 한 간단한 알고리즘의 큰 차이와 Fisher-Yates
알고리즘의 신뢰성을 확인할 수 있습니다.
Underscore.js
또는Lo-Dash
라이브러리로 배열 셔플
유명한Underscore.js
라이브러리는 알고리즘 구현을 작성할 필요없이 배열을 직접 무작위화할 수있는 셔플 함수도 제공합니다.
_.shuffle()
메서드를 사용하는 다음 예제를 살펴 보겠습니다.
먼저 HTML 템플릿 내에서 Cloudflare CDN
을 사용하여 라이브러리를 가져와야합니다.
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
그런 다음 다음과 같이_.shuffle()
메서드를 사용합니다.
var tmpUnderscoreArray = [1, 3, 5];
resultArray = _.shuffle(tmpUnderscoreArray);
console.log(resultArray);
출력:
(3) [1, 5, 3]