이 글에서는 배열의 배열을 인자로 받아, 원본 배열에 담긴 모든 요소를 하나로 모으되 중복된 항목은 제거하고 고유한 값만 남긴 새로운 배열을 반환하는 JavaScript 함수를 만들어 보겠습니다.
문제 정의
예를 들어 다음과 같은 입력이 주어졌다고 가정해 봅시다.
const arr = [
[12, 45, 65, 76, 76, 87, 98],
[54, 65, 98, 23, 78, 9, 1, 3],
[87, 98, 3, 2, 123, 877, 22, 5, 23, 67]
];기대하는 출력은 여러 배열에 흩어져 있던 요소들을 하나의 배열로 합치되, 두 번 이상 등장한 값은 완전히 제거한 고유 요소 목록입니다.
[
12, 45, 54, 78, 9,
1, 2, 123, 877, 22,
5, 67
]위 결과를 보면 65, 76, 87, 98, 23, 3처럼 한 번 이상 반복해서 나타난 숫자들은 모두 사라지고, 딱 한 번만 등장한 숫자들만 남는 것을 확인할 수 있습니다.
구현 예제
const arr = [
[12, 45, 65, 76, 76, 87, 98],
[54, 65, 98, 23, 78, 9, 1, 3],
[87, 98, 3, 2, 123, 877, 22, 5, 23, 67]
];
const getUnique = (arr) => {
const newArray = [];
arr.forEach((el) => newArray.push(...el));
return newArray.filter((item, index) => {
return newArray.indexOf(item) === newArray.lastIndexOf(item);
});
};
console.log(getUnique(arr));코드 동작 원리
- 배열 평탄화: forEach와 전개 연산자(...)를 사용해 중첩된 배열들의 모든 요소를 newArray 하나로 합칩니다.
- 중복 필터링: filter 안에서 indexOf(item)과 lastIndexOf(item)를 비교합니다. 두 값이 같다는 것은 해당 요소가 배열 전체에서 단 한 번만 등장한다는 의미이므로, 이 조건을 만족하는 요소만 최종 결과에 남게 됩니다.
실행 결과
콘솔에는 다음과 같이 출력됩니다.
[
12, 45, 54, 78, 9,
1, 2, 123, 877, 22,
5, 67
]참고: flat()으로 더 간결하게 작성하기
ES2019부터 지원되는 Array.prototype.flat() 메서드를 사용하면 평탄화 과정을 훨씬 간결하게 표현할 수 있습니다.
const getUnique = (arr) => {
const flattened = arr.flat();
return flattened.filter(
(item) => flattened.indexOf(item) === flattened.lastIndexOf(item)
);
};다만 위 방식은 indexOf와 lastIndexOf를 매 요소마다 호출하므로 시간 복잡도가 O(n²)입니다. 데이터 크기가 클 경우에는 Map이나 객체를 사용해 각 값의 등장 횟수를 미리 세어 놓은 뒤 필터링하는 방식이 성능 면에서 더 유리합니다.