정렬된 숫자 배열에는 다음과 같이 연속된 숫자들이 포함될 수 있습니다.
const arr = [1, 2, 3, 5, 7, 8, 9, 11];
우리는 이러한 배열을 인자로 받는 JavaScript 함수를 작성해야 합니다.
이 함수의 역할은 배열 전체를 하나의 시퀀스 문자열로 만드는 것입니다. 규칙은 간단합니다. 배열에서 연속으로 이어지는 숫자 구간은 시작 숫자와 끝 숫자만 남기고 그 사이의 숫자들은 대시(-)로 축약하며, 연속되지 않은 나머지 숫자들은 원래 그대로 표기합니다.
따라서 위 배열의 경우 결과는 다음과 같아야 합니다.
const output = '1-3,5,7-9,11';
동작 방식
구현 로직을 단계별로 살펴보면 다음과 같습니다.
- 배열을 순회하면서 현재 값에 1을 더한 값이 다음 요소와 일치하는지 확인합니다. 일치한다면 두 숫자는 연속된 관계입니다.
- 연속 구간이 시작되면 해당 구간의 첫 번째 숫자를 별도 변수(pointer)에 저장해 둡니다.
- 연속 구간이 끝나는 지점(다음 요소가 현재 값 + 1이 아닌 지점)에 도달하면, 저장해 둔 시작 숫자와 현재 값을 대시로 이어 붙여
시작-끝형태로 결과 배열에 추가합니다. - 연속되지 않은 단독 숫자는 그대로 결과 배열에 추가합니다.
- 마지막으로 모든 요소를 쉼표(,)로 연결하여 최종 문자열을 반환합니다.
예제 코드
이를 구현한 코드는 다음과 같습니다.
const arr = [1, 2, 3, 5, 7, 8, 9, 11];
const buildSequence = (arr = []) => {
let pointer;
return arr.reduce((acc, val, ind) => {
if (val + 1 === arr[++ind]) {
if (pointer == null) {
pointer = val;
};
return acc;
};
if (pointer) {
acc.push(`${pointer}-${val}`);
pointer = null;
return acc;
}
acc.push(val);
return acc;
}, []).join(',');
}
console.log(buildSequence(arr));출력 결과
콘솔에 출력되는 결과는 다음과 같습니다.
1-3,5,7-9,11
이처럼 reduce() 메서드와 외부 참조 변수를 활용하면 반복문 없이도 깔끔하게 연속 구간을 압축한 시퀀스 문자열을 생성할 수 있습니다. 데이터 압축 표기나 로그 요약 등 실무에서도 유용하게 응용할 수 있는 패턴입니다.