LHJ

I'm a FE developer.

4.3.4 배열을 수정할 때 감소하는 인덱스 사용하기

20 Apr 2020 » js_lj

배열에 루프를 실행하면서 루프 바디에서 배열을 수정하는 건 위험할 수 있습니다.
뜻하지 않게 종료 조건을 바꿀 수도 있으니까요.
운이 좋다면 원하지 않는 결과가 나오는 정도겠지만, 운이 나쁘면 무한 루프가 발생할 겁니다.
이런 경우 널리 쓰이는 패턴은 감소하는 인덱스를 써서, 배열 마지막 요소에서 루프를 시작하는 방법입니다.
이렇게 하면 배열에 요소를 추가하거나 제거해도 종료 조건이 바뀌는 일은 없습니다.

예를 들어 bitArrayOfNumbers 에서 찾은 모든 소수를 제거하고 싶다고 합시다.
8장에서 배우겠지만, 다음 코드의 splice 메서드는 배열 요소를 추가하거나 제거할 때 사용합니다.
이 예제는 예상대로 동작하지 않습니다.

for(let i=0; i<bigArrayOfNumbers.length; i++) {
	if(isPrime(bigArrayOfNumbers[i])) bigArrayOfNumbers.splice(i, 1);
}

인덱스는 점점 커지는데 우리는 요소를 제거하고 있으므로, 소수가 연달아 존재한다면 그중 일부를 제거하지 않고 넘어갈 가능성이 있습니다.
감소하는 인덱스를 쓰면 이 문제는 간단히 해결됩니다.

for(let i = bigArrayOfNumbers.length-1; i>=0; i--){
	if(isPrime(bigArrayOfNumbers[i])) bigArrayOfNumbers.splice(i, 1);
}

초기 조건과 종료 조건을 봅시다.
배열의 인덱스는 0에서 시작하므로 배열 길이보다 1 작은 값으로 시작해야 합니다.
그리고 루프의 종료 조건을 i가 0보다 크거나 같을 때로 정했습니다.
그렇지 않다면 이 루프는 배열의 첫 번째 요소에서는 실행되지 않으므로, 첫 번째 요소가 소수라면 문제가 생길 겁니다.