이번 글에서는 리터럴 값으로 이루어진 배열을 입력받아, 배열 안에 포함된 '#'의 인덱스 위치는 그대로 유지하면서 나머지 요소들만 반전시키는 JavaScript 함수를 작성해 보겠습니다.
예를 들어 다음과 같은 배열이 주어졌을 때,
[18, -4, '#', 0, 8, '#', 5]
기대하는 결과는 아래와 같습니다.
[5, 8, "#", 0, -4, "#", 18]
즉, 숫자 요소들은 서로 뒤바뀌지만 '#'은 원래 자리(인덱스)에 그대로 남아 있어야 합니다.
구현 예제 코드
const arr = [18, -4, '#', 0, 8, '#', 5];
const arr1 = [18, -4, 0, '#', 8, '#', 5];
const specialReverse = (arr = []) => {
let removed = arr.reduce((acc, val, ind) => {
return val === '#' ? acc.concat(ind) : acc;
}, []);
let reversed = arr.filter(val => val !== '#').reverse();
removed.forEach(el => reversed.splice(el, 0, '#'));
return reversed;
};
console.log(specialReverse(arr));
console.log(specialReverse(arr1));출력 결과
콘솔에 출력되는 결과는 다음과 같습니다.
[ 5, 8, '#', 0, -4, '#', 18 ] [ 5, 8, 0, '#', -4, '#', 18 ]
코드 동작 원리
위 함수의 로직은 크게 세 단계로 나눌 수 있습니다.
1단계: '#'의 인덱스 추출
reduce() 메서드를 사용해 배열을 순회하면서 값이 '#'인 요소의 인덱스만 별도의 배열(removed)에 모읍니다. 이렇게 하면 나중에 '#'을 정확히 원래 위치에 되돌려 놓을 수 있습니다.
2단계: 숫자 요소만 반전
filter()로 '#'을 제외한 숫자 요소들만 추출한 뒤, reverse()를 호출해 순서를 뒤집습니다.
3단계: '#'을 원래 인덱스에 삽입
1단계에서 저장해 둔 인덱스 정보를 이용해 splice()로 각 위치에 '#'을 다시 삽입합니다. 삽입 시 기존 요소는 뒤로 밀려나므로, 앞쪽 인덱스부터 차례대로 처리해도 위치가 어긋나지 않습니다.
이 세 단계를 거치면 숫자는 완전히 반전되면서도 '#'의 위치는 절대 변하지 않는 배열을 얻을 수 있습니다.