방법은 몇 가지가 있는 것 같다
방법 1.
const arr = [
"a",
"b",
"c",
];
// 배열 arr
const randomValueFromArray = (array) => {
const random = Math.floor(Math.random() * array.length); // 0~2 사이의 랜덤 숫자가 random에 들어간다
return array[random]; // 0~2 사이의 랜덤 정수가 들어가서 값을 구한다
// 만약 random 값이 2라면 'c'가 나온다
}
console.log(randomValueFromArray(arr));
하지만 이것은 배열을 무작위로 섞는 것이 아니라
배열을 무작위로 하나씩 가져오는 방법이다.
만약 무작위로 섞어서 다른 배열을 만들거라면
함수를 배열의 length만큼 돌리고 그 값을 새로운 array에 따로 저장하면 될 듯.
방법 2.
<AnswerList>
{/* 문제 랜덤하게 섞기 */}
{qList.questionList[qNumber].answerList
.sort(() => Math.random() - 0.5)
.map((selector) => (
<Answer
onClick={answerClick}
data-value={selector.candidate}
key={selector.answer}
>
{selector.answer}
</Answer>
))}
</AnswerList>
나는 이렇게 구성했다
무슨말인지..
모르겠죠?
console.log(
qList.questionList[qNumber].answerList.sort(() => Math.random() - 0.5)
);
// 여기서 qList.questionList[qNumber].answerList를 하나의 배열로 보면 된다.
// => 배열.sort로 0~1까지의 랜덤 숫자에서 0.5를 뺀 값을 준다.
// 즉, 랜덤하게 들어간 값 -0.5로 자연스럽게 랜덤정렬된다.
// 더 쉽게 고치면
const arr = qList.questionList[qNumber].answerList; // 원하는 배열 넣기
console.log(arr.sort(() => Math.random() - 0.5));
이렇게 된다.
질문
왜 Math.random()에서 0.5를 빼나요?
그래서 해보았다
console.log(arr.sort(() => Math.random() - 0.5)); // 잘 나온다
console.log(arr.sort(() => Math.random() - 1)); // 섞이지 않는다
console.log(arr.sort(() => Math.random())); // 섞이지 않는다
console.log(arr.sort(() => Math.random() + 1)); // 섞이지 않는다
console.log(arr.sort(() => Math.random() - 0.7)); // 섞이기는 한다
이것을 위해서 sort에 대한 이해가 필요하다
sort는
1. a, b 형식으로 지정된 인자를 차례로 비교한다
2. 비교 결과값이 양수가 나올 때
3. 양수값을 전달받은 sort 함수는 배열의 값을 교체한다
4. 이런식으로 계속 두 인자를 비교해서 결과값이 0보다 크면 순서를 바꾸고, 0보다 작으면 바꾸지 않는다
5. 이렇게 정렬된다
배열이 바뀌어가는 순서를 보면 이해하기 쉽습니다.
[(20), (10), 9,8,7,6,5,4,3,2,1] 20-10 = 10, 즉 양수이므로 순서바뀜! ()는 비교되는 인자값.
[(10), 20, (9),8,7,6,5,4,3,2,1] 10 - 9 = 1 또 양수, 순서 바뀜.
[(9), 20, 10, (8),7,6,5,4,3,2,1] 반복...
[(8), 20, 10, 9,(7)...]
...
[(2). 20, 10...3, (1)]
[(1), 20, 10...]
그럼 배열 내에서 가장 작은 값 1이 찾아지겠죠.
[1, 20, 10, 9,8,7,6,5,4,3,2]
1의 순서는 바뀌지 않습니다. 1-2 = -1
즉 결과값이 음수이기 때문이죠.
그 다음은 두번째 배열 차례입니다.
20 - 10 = 10 > 0 이므로 순서를 또 바꿉니다.
[1, (20), (10), 9,8,7,6,5,4,3,2]
[1, (10), 20, (9), 8...]
[1, (9), 20, 10, (8)...]
이런 식으로 반복하다 보면 두번째로 작은 값 2도 찾게 됩니다.
....
[1, 2, 20, 10, 9,8,7,6,5,4,3]
그럼 다음은 세번째...
이렇게 지루하게 반복하면 결국 정렬이 됩니다.
물론 실제 자바스크립트에서는 비교하는 순서가 다릅니다.
다른 알고리즘을 쓰기 때문이죠.
이렇게 차례차례 비교해 나가면 인간이 이해하기는 쉽지만
연산량이 기하급수적으로 늘어나기 때문에 다른 정렬 알고리즘을 쓰는 것이죠.
실제로는
[20, 10, 9,8,7,6,5,4,3,2,1]
배열의 양쪽 끝부터 비교하고 (20, 1),
그 다음 배열의 가운데 값을 차례로 비교해 나갑니다. (1,6)
디버깅해 보시면 쉽게 아실 수 있을 겁니다
출처 - 댓글에서퍼옴
https://opentutorials.org/course/50/109
을 또 퍼옴
출처 : https://noirstar.tistory.com/359
==> sort는 뺀 값이 양수가 되면 자리를 바꾸고
음수면 자리를 바꾸지 않는다
그러니까 [3,2,1].sort((a,b) => a-b)를 하면
1. 3-2이 양수이므로 자리를 바꾸지 않는다
2. 3-1이 양수이므로 자리를 바꾸지 않는다
3. 2-1이 양수이므로 자리를 바꾸지 않는다
반대로
[1,2,3,4].sort((a,b) => b-a)를 하면
1. 4-1이 양수이므로 자리를 바꾼다 [4,2,3,1]
2. 3-2이 양수이므로 자리를 바꾼다 [4,3,2,1]
이런식으로 작동된다(아아아아아~주 간추렸고 실수한 점이 있을 수도 있으니 주의!)
따라서 다시 우리의 질문을 보면
console.log(arr.sort(() => Math.random() - 0.5)); // 잘 나온다
// => 0~1사이의 난수를 만드는 random함수에서 0.5를 빼면 확률적으로 섞이고 섞이지 않을 확률이 반반이다.
console.log(arr.sort(() => Math.random() - 1)); // 섞이지 않는다
// => 결과는 항상 음수가 나온다. 즉, 섞이지 않는다
console.log(arr.sort(() => Math.random())); // 섞이지 않는다
// => 당연함.
console.log(arr.sort(() => Math.random() + 1)); // 섞이지 않는다
// => 이것도.. 당연함. 모르겠으면 [1,2,3]으로 한번 섞어보자.
console.log(arr.sort(() => Math.random() - 0.7)); // 섞이기는 한다
// => 섞일 확률이 0.5보다 더 작아진다. random값이 0.7보다 클 때만 섞이기 때문.
그렇다면..
질문 하나만 더
0.3은? 더 잘 섞이려나?
console.log(["a", "b", "c", "d", "e"].sort(() => Math.random() - 0.3)); // 잘 나온다
// => 하지만 0.5가 아닌 0.3을 빼야 할 이유를 모르겠다.
그냥 확률적으로 양수와 음수가 나올 확률이 반반인 0.5를 이용하는게 좋아 보인다.
🙇♀️
https://7942yongdae.tistory.com/96
https://suinautant.tistory.com/584
https://noirstar.tistory.com/359
'✍ 공부 > JavaScript' 카테고리의 다른 글
JavaScript 자바스크립트 이벤트 리스너(eventListener) (0) | 2022.06.11 |
---|---|
Babel이란 무엇일까? (0) | 2022.04.17 |
[프론트앤드 공부기록] Javascript 기초 4 (0) | 2021.08.16 |
[프론트앤드 공부기록] Javascript 기초 3 (0) | 2021.08.14 |
[프론트앤드 공부기록] Javascript 기초 2 (0) | 2021.08.13 |