Вы можете имитировать набор массивов с вложенными картами, где [1, 2] становится записью в корневой карте, где ключ равен 1, а значением является другая карта с ключом 2, например:
const present = Symbol('present');
class ArraySet {
constructor() {
this._root = new Map();
}
add(array) {
let node = this._root;
for (const item of array) {
if (node.has(item)) {
node = node.get(item);
} else {
node.set(item, node = new Map());
}
}
node[present] = true;
}
has(array) {
let node = this._root;
for (const item of array) {
node = node.get(item);
if (node === undefined) {
return false;
}
}
return !!node[present];
}
}
тогда:
const compareArrs = (arr1, arr2) => {
const set = new ArraySet();
arr1.forEach(set.add, set);
return arr2.filter(set.has, set);
};
const present = Symbol('present');
class ArraySet {
constructor() {
this._root = new Map();
}
add(array) {
let node = this._root;
for (const item of array) {
if (node.has(item)) {
node = node.get(item);
} else {
node.set(item, node = new Map());
}
}
node[present] = true;
}
has(array) {
let node = this._root;
for (const item of array) {
node = node.get(item);
if (node === undefined) {
return false;
}
}
return !!node[present];
}
}
const compareArrs = (arr1, arr2) => {
const set = new ArraySet();
arr1.forEach(set.add, set);
return arr2.filter(set.has, set);
};
console.log(compareArrs([[1, 2], [3, 4]], [[1, 2]]));
Это занимает время, пропорциональное arr1.concat(arr2).flat().length
. Другой подход, который работает до тех пор, пока вы можете создать подходящую функцию сравнения для массивов, как этот лексикографический, когда обычные операторы JavaScript дают полный порядок:
const lexCompare = (a, b) => {
const len = Math.min(a.length, b.length);
for (let i = 0; i < len; i++) {
if (a[i] < b[i]) return -1;
if (a[i] > b[i]) return 1;
}
return a.length - b.length;
};
и входные массивы не содержат дубликатов - сначала сортировать комбинацию обоих массивов:
const sorted = arr1.concat(arr2).sort(lexCompare);
затем ищите дубликаты, созданные слиянием рядом друг с другом:
return sorted.filter((item, i) => {
if (i === 0) return false;
const prev = sorted[i - 1];
return prev.length === item.length && prev.every((x, i) => x === item[i]);
});
за время O ((| arr1 | + | arr2 |) log (| arr1 | + | arr2 |) l) где l - максимальная длина массива. Вы можете уменьшить этот (| arr1 | + | arr2 |) log (| arr1 | + | arr2 |) до | arr1 | log | arr1 | + | arr2 | log | arr2 | но это может закончиться медленнее.