JavaScript so sánh mảng bằng === hoặc == kiểm tra tham chiếu (reference), không phải giá trị. [1,2] === [1,2] là false. Để so sánh nội dung (value), cần thuật toán tùy mục đích.
1. Tìm phần tử chung (Intersection) - Giống ví dụ gốc
const arr1 = [50, 60, 65, 90];
const arr2 = [25, 35, 50, 90];
// Cách đơn giản (O(n*m)) - Chỉ dùng mảng nhỏ
const common = [];
for (let i = 0; i < arr1.length; i++) {
for (let j = 0; j < arr2.length; j++) {
if (arr1[i] === arr2[j]) {
common.push(arr1[i]);
}
}
}
console.log(common); // [50, 90]
2. Cách hiệu quả (O(n+m)) - Dùng Set (Khuyên dùng)
const arr1 = [50, 60, 65, 90];
const arr2 = [25, 35, 50, 90];
const set2 = new Set(arr2); // O(m)
const common = arr1.filter(x => set2.has(x)); // O(n)
console.log(common); // [50, 90] - Giữ thứ tự arr1, loại trùng lặp trong arr1 nếu có
3. Kiểm tra 2 mảng GIỐNG HỆT (Same elements, same order)
function arraysEqual(arr1, arr2) {
if (arr1.length !== arr2.length) return false;
for (let i = 0; i < arr1.length; i++) {
if (arr1[i] !== arr2[i]) return false;
}
return true;
}
// Hoặc dùng JSON (chỉ cho kiểu dữ liệu đơn giản, không function, circular)
function arraysEqualJSON(arr1, arr2) {
return JSON.stringify(arr1) === JSON.stringify(arr2);
}
console.log(arraysEqual([1,2,3], [1,2,3])); // true
console.log(arraysEqual([1,2,3], [1,3,2])); // false
4. Kiểm tra 2 mảng CÙNG PHẦN TỬ (Bỏ qua thứ tự)
function arraysEquiv(arr1, arr2) {
if (arr1.length !== arr2.length) return false;
const count = {};
for (const x of arr1) count[x] = (count[x] || 0) + 1;
for (const x of arr2) {
if (!count[x]) return false;
count[x]--;
}
return true;
}
console.log(arraysEquiv([1,2,3], [3,2,1])); // true
console.log(arraysEquiv([1,2,2], [2,1,1])); // false
5. So sánh mảng Object (Deep Compare)
const arr1 = [{id: 1}, {id: 2}];
const arr2 = [{id: 1}, {id: 2}];
// Cần so sánh sâu (deep equal) - dùng thư viện hoặc viết đệ quy
// Lodash: _.isEqual(arr1, arr2)
// Hoặc custom:
function deepEqual(a, b) {
if (a === b) return true;
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) return false;
if (Array.isArray(a) !== Array.isArray(b)) return false;
if (a.length !== b.length) return false;
for (let i = 0; i < a.length; i++) {
if (!deepEqual(a[i], b[i])) return false;
}
return true;
}
So sánh hiệu năng & Ứng dụng
| Mục đích | Phương pháp | Độ phức tạp | Lưu ý |
|---|---|---|---|
| Tìm phần tử chung | arr1.filter(x => new Set(arr2).has(x)) | O(n+m) | Nhanh, giữ thứ tự arr1 |
| Kiểm tra giống hệt (cùng thứ tự) | Vòng lặp index hoặc JSON.stringify | O(n) | JSON fail với function, Symbol, circular |
| Kiểm tra cùng phần tử (khác thứ tự) | Frequency Counter (Object/Map) | O(n+m) | Chuẩn xác cho primitive |
| So sánh object/array lồng nhau | Lodash _.isEqual hoặc custom deepEqual | O(n) | Xử lý circular, Date, Regex, Map, Set |
Ví dụ gốc (Tìm phần tử trùng) - Cải tiến
<html>
<body>
<script>
var arr1 = [50, 60, 65, 90];
var arr2 = [25, 35, 50, 90];
// Tối ưu với Set
var set2 = new Set(arr2);
var matched = arr1.filter(x => set2.has(x));
matched.forEach(val => document.write("Matched element: " + val + "<br>"));
// Output: Matched element: 50, Matched element: 90
</script>
</body>
</html>
Tóm lại: JS không so sánh mảng bằng ===. Dùng Set + filter để tìm phần tử chung (nhanh, O(n+m)). Dùng vòng lặp index hoặc JSON.stringify (cẩn thận) để kiểm tra giống hệt. Dùng frequency counter cho cùng phần tử khác thứ tự. Object/Array lồng -> _.isEqual hoặc deepEqual custom.