强文本在两个输入数组之间,找到相同的一个或多个数组并返回它们。
我只是想出了嵌套循环解决方案。
const compareArrs = (arr1, arr2) => {
const rtnArr = []
for (let ar1 of arr1){
for (let ar2 of arr2){
if (JSON.stringify(ar1) === JSON.stringify(ar2)){
rtnArr.push(ar1)
}
}
}
return rtnArr
}
// compare [1, 2] [3, 4] with [1, 2]
console.log(compareArrs([[1, 2], [3, 4]], [[1, 2]]))
[[1,2]]应该返回
答案 0 :(得分:1)
映射一个参数的每个子数组并将其放入Set中。与另一个参数一起迭代遍历,随即进行字符串化处理,并在集合中找到已字符串化数组的元素,总体复杂度为O(N)
:
const compareArrs = (arr1, arr2) => {
const arr1StringifiedSet = new Set(arr1.map(JSON.stringify));
return arr2.find(
subarr2 => arr1StringifiedSet.has(JSON.stringify(subarr2))
);
};
console.log(compareArrs([[1, 2], [3, 4]], [[1, 2]]));
(相比之下,嵌套循环的复杂度为O(N^2)
)
如注释所示,如果您实际上需要 all 个匹配数组,而不仅仅是第一个,则使用.filter
而不是.find
:
const compareArrs = (arr1, arr2) => {
const arr1StringifiedSet = new Set(arr1.map(JSON.stringify));
return arr2.filter(
subarr2 => arr1StringifiedSet.has(JSON.stringify(subarr2))
);
};
console.log(compareArrs([[1, 2], [3, 4]], [[1, 2]]));
答案 1 :(得分:1)
您可以模拟一组带有嵌套映射的数组,其中[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 |)日志(| arr1 | + | arr2 |)减少为| arr1 |日志| arr1 | + | arr2 |日志| arr2 |但最终可能会变慢。
答案 2 :(得分:1)
您可以将Array.prototype.reduce()与Array.prototype.find()和Array.prototype.push()组合使用
const compareArrs = (arr1, arr2) => arr1.reduce((a, c) => {
const found = arr2.find(arr => JSON.stringify(arr) === JSON.stringify(c))
if (found.length) a.push(found)
return a
}, [])
// compare [1, 2] [3, 4] with [1, 2]
console.log(compareArrs([[1, 2]], [[1, 2], [3, 4]]))