참고: https://www.30secondsofcode.org/articles/s/javascript-array-comparison
단순 비교
JavaScript에서 느슨하거나 엄격한 등가연산자(== 또는 ===)로 두개의 배열을 비교하면 대부분의 결과는 false가 됩니다. 심지어 두개의 배열이 동일한 항목을 동일한 순서로 가지고 있더라고 마찬가지입니다. 왜 이런 결과가 나오냐면 JavaScript에서 배열과 객체는 값을 비교하는게 아니라 객체의 주소를 비교하기 때문입니다. 이는 다음의 예제는 원하는 결과를 내주지 않는다는 말입니다.
const a = [1, 2, 3];
const b = [1, 2, 3];
a === b; // false
JSON.stringify
일반적인 해결 방법으로 많은 사람들이 JSON.stringify() 메소드를 사용합니다. 이는 각각의 배열을 serialize 하고 이 serialize된 두개의 문자열을 비교할 수 있게 해줍니다. 간단한 구현 방법은 다음과 같습니다.
const equals = (a, b) => JSON.stringify(a) === JSON.stringify(b);
const a = [1, 2, 3];
const b = [1, 2, 3];
equals(a, b); // true
그냥 보기에는 아주 좋아 보입니다. 짧고 간단하게 이해가능한 솔루션입니다. 하지만 이는 다음의 예제처럼 다른 값이 같은 문자열로 serialize되는 특정 사례에서 실패합니다.
const str = 'a';
const strObj = new String('a');
str === strObj; // false
equals([str], [strObj]); // true, should be false
null === undefined; // false
equals([null], [undefined]); // true, should be false
이런 경우가 흔하지는 않지만 나중에 이슈가 발생했을 때 디버깅하고 수정하기 아주 힘들어질 수 있습니다. 이러한 이유로 이 솔루션은 대부분의 경우에서 추천되지 않습니다.
더 나은 방법
두 배열의 길이와 Array.prototype.every() 메소드를 사용해 비교하는 더 나은 방법이 있습니다.
const equals = (a, b) =>
a.length === b.length &&
a.every((v, i) => v === b[i]);
const a = [1, 2, 3];
const b = [1, 2, 3];
const str = 'a';
const strObj = new String('a');
equals(a, b); // true
equals([str], [strObj]); // false
equals([null], [undefined]); // false
이 접근방법은 위에서 언급한 직렬화관련 이슈에 보호장치를 가집니다. 하지만 이는 중첩된 배열이나 객체에 대해서는 적용되지 않습니다. 이 문제까지 해결하려면 재귀적으로 반복확인을 해야합니다. 이런 중첩 문제나 다른 이슈들을 보완하는 해결책을 만드려면 equals snippet 까지 적용해야합니다.
순서없이 비교
마지막으로 각각의 배열내 항목의 순서가 중요하지 않고 오직 동일한 항목들이 존재하는지만이 중요한 경우가 있을 수 있습니다. 이런 경우는 Set과 Array.prototype.filter() 메소드를 사용하여 Set으로 만든 유일한 값을 루프돌게하여 각각의 배열에 같은 양의 항목이 있는지 확인하는 식으로 만들면 됩니다.
const equalsIgnoreOrder = (a, b) => {
if (a.length !== b.length) return false;
const uniqueValues = new Set([...a, ...b]);
for (const v of uniqueValues) {
const aCount = a.filter(e => e === v).length;
const bCount = b.filter(e => e === v).length;
if (aCount !== bCount) return false;
}
return true;
}
더 자세한 설명은 haveSameContents snippet을 확인하기 바랍니다.
'dev > javascript' 카테고리의 다른 글
[express.js] post 받는 서버 만들기 (0) | 2022.09.01 |
---|---|
[javascript] 자바스크립트 키보드 입력 추가하기 (엔터키 입력) (0) | 2022.08.31 |
[javascript] 자바스크립트 정규식으로 메일 주소 검증 (0) | 2022.08.02 |
[javascript] 자바스크립트 배열에서 최대/최소 구하는 방법 (min, max) (0) | 2022.07.05 |
[javascript] 자바스크립트 base64 사용 방법 (btoa, atob) (0) | 2022.06.30 |
댓글