underbar shuffle

멜로디·2021년 2월 22일
0

기수이동

목록 보기
1/3

코드

_.shuffle = function (arr) { 
  let arrCloned = arr.slice();
  // 함수에 입력된 인자값을 수정하지 않고 arrCloned 변수에 인자값으로 입력받은 배열을 복사한다.

  for (let fromIdx = 0; fromIdx < arr.length; fromIdx++) {
    const toIdx = Math.floor(Math.random() * arr.length);
    // toIdx는 (0 이상  1미만의 난수)와 (배열의 길이)를 곱한 값에서 소숫점 이하를 버린 값.
    let temp = arrCloned[fromIdx];
    // temp는 입력 배열의 n번째 요소. 반복문의 반복 횟수가 늘어날 수록 n번째는 점진적 증가.
    arrCloned[fromIdx] = arrCloned[toIdx];
    // 입력 배열의 n번째 요소는 입력 배열의 i번째 요소
    arrCloned[toIdx] = temp;
    // 입력 배열의 i번째 요소는 입력 배열의 n번째 요소
  }

  return arrCloned;

};

순서

  1. 임의의 인덱스를 랜덤하게 만든다 (순서할당)
  2. 배열의 인덱스를 뒤섞는다 (뒤섞기)
  3. 1~2를 배열이 끝날 때 까지 반복한다 (반복조건)

순서할당

순서를 섞을 때에는 순서를 이리저리 랜덤하게 섞어야 한다.
위 코드에서는 순서를 랜덤하게 배정하기 위해 Math.floor(Math.random() * arr.length) 를 사용했다.

Math.random()은 0보다 크고 1보다 작은(0 < n < 1) 임의의 난수를 생성하는 js 내장 메소드이다. (반복문이 반복할때마다 난수를 새로 생성한다)

이렇게 생성한 난수에 배열의 길이를 곱해주어야 하는데,
배열의 index를 뒤섞어 주어야 하기 때문에 배열의 길이를 곱하여 배열의 길이만큼만 분리할 수 있도록 한다.
난수에 배열의 길이를 곱하여 생긴 숫자는, 인덱스 지정을 할 수 있도록 Math.floor()를 이용하여 소숫점 이하를 버린다.

순서 할당의 key point
배열의 길이를 곱해주어 임의의 index가 배열의 길이만큼만 생성되도록 한다

Math.floor(Math.random() * arr.length)
arr.length가 3일 경우 : 1~2 생성
arr.length가 5일 경우 : 1~4 생성
arr.length가 7일 경우 : 1~6 생성
arr.length가 9일 경우 : 1~8 생성

이와 같이 arr.length -1의 임의의 값을 생성하기 때문에 셔플에 쓰기 좋다.

뒤섞기

반복문이 돌면서 toIdx에서 생성한 랜덤 인덱스를 이용하여 배열의 순서를 섞을 차례이다.
입력 받은 배열을 0번째 인덱스부터 마지막까지 순차적으로 순서를 바꾸기 위해
let temp = arrCloned[fromIdx]
위와 같이 temp라는 변수에 배열의 fromIdx번째 인덱스를 할당한다.
fromIdx는 반복문의 조건에서도 볼 수 있듯, 0부터 arr.length -1까지 점진적으로 증가한다.

그리고 arrCloned[fromIdx] = arrCloned[toIdx]를 이용하여 위치를 재할당 하고, toIdx번째 위치에 있던 요소를 fromIdx번째 위치로 재할당하여 옮긴다.

뒤섞기의 key point
얼핏 보면 2번의 재할당을 왜 하는지 이해하기 어려울 수 있지만, 작동하는 로직을 이해하면 쉽다.

let temp = arrCloned[fromIdx]
arrCloned[fromIdx] = arrCloned[toIdx]
arrCloned[toIdx] = temp

이 코드에서 하는 역할은 간단하다. fromIdx번째 요소와 toIdx번째 요소를 맞바꾸는 것이다.

fromIdx가 1이고 toIdx가 3일때,
  let temp = arrCloned[1]
arrCloned[1] = arrCloned[3]
arrCloned[3] = arrCloned[1]

이런 식으로 간단하게 각 인덱스의 요소를 맞바꾸어 주는 것 뿐이다.

결론

코드는 어렵게 생각할 것 없이 로직만 잘 생각하면 술술 써내려 갈 수 있다.

profile
하루하루 배울때마다 기록하는 일기장

0개의 댓글