猿问

对于两个数组,查找仅存在于一个数组中的项目(对称差异)

我需要比较两个数组并返回一个新数组,其中包含仅在两个给定数组之一中找到的任何项目,但不能同时在两个数组中找到。换句话说,返回两个数组的对称差。我的算法包括在第一个数组上使用 map() 方法,并使用 every() 将该数组的每个元素与第二个数组的元素进行比较。如果此方法返回 true,则该元素将在 map 的块级别返回(最终会将其添加到返回的数组),否则将被丢弃。我不确定为什么我的代码不起作用。这是使用我的代码的错误输出示例:


function diffArray(arr1, arr2) {

    var newArr = arr1

        .map(elem1 => {

            if (arr2.every(elem2 => elem2 != elem1)) {

                return elem1;

            }

        });

    return newArr;

}


console.log(diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]));

这是错误的输出:[ undefined, undefined, undefined, undefined ]


预期输出是:[4]


白板的微信
浏览 158回答 4
4回答

万千封印

您的方法迭代第一个数组,并且由于使用map以及对值的检查,您得到 undefined 的每个元素arr1。如果您filter也使用另一个数组,您可以获得想要的结果。function diffArray(arr1, arr2) {    return [        ...arr1.filter(elem1 => arr2.every(elem2 => elem2 != elem1)),        ...arr2.filter(elem1 => arr1.every(elem2 => elem2 != elem1))    ];}console.log(diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]));另一种方法采用两个数组的所有值组成的数组,并通过检查该值是否不包含在两个数组中来进行过滤。function diffArray(arr1, arr2) {    return [...arr1, ...arr2].filter(v => arr1.includes(v) !== arr2.includes(v));}console.log(diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]));

qq_花开花谢_0

即使数字在两个数组中多次出现,该算法也能正常工作。它使用从两个数组的项目创建的 Map。该地图包含该项目作为键,该值是它在第一个数组中找到的次数 - 它在第二个数组中找到的次数。创建 Map 后,它会转换为 [item, count] 的数组。然后过滤数组,删除所有计数为的项目0(它们在两个数组中均等存在),然后我们将数组映射到项目数组。const getCounts = (arr, init = new Map(), inc = 1) =>  arr.reduce((acc, item) => acc.set(item, (acc.get(item) || 0) + inc), init);function diffArray(arr1, arr2) {  // create a Map that adds 1 for all items in arr1, and substructs 1 for every item in arr2  const counts = getCounts(arr2, getCounts(arr1), -1);    // convert to an array of pairs [item, count]  return Array.from(counts)    .filter(([, v]) => v) // remove all items with count 0    .map(([k]) => k); // map to the original item}console.log(diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]));console.log(diffArray([1, 2, 3, 3, 5], [1, 2, 3, 4, 5]));console.log(diffArray([5, 1, 2, 3, 5], [1, 2, 3, 4, 5, 5]));console.log(diffArray([1, 1, 2, 2, 3, 3, 5], [1, 2, 2, 3, 4, 5]));

MMTTMM

您的函数返回第二个数组中不存在的第一个数组的元素。.map()它的返回是通过返回与您的输入 ( ) 大小完全相同的数组这一事实来解释的arr1,但是由于所有项目都arr1存在于arr2您不输入if(-statement 正文中,因此undefined被返回。如果您的目的是返回仅存在于一个数组中的项目(无论它们传入的顺序如何),您可以将该Map对象与Array.prototype.reduce():将数组参数组合成普通的数组数组使用 循环遍历这些内部数组.reduce(),构建Map,显示每个项目在组合数组中出现的次数对于组合数组的每个项目,删除重复项并增加相应的计数器传播结果Map和.entries()那些.filter()找出独特之处const arr1 = [1, 2, 3, 5],       arr2 = [1, 2, 3, 4, 5],            getUniques = (...arrays) =>         [...arrays          .reduce((acc, arr) => {            [...new Set(arr)]              .forEach(item =>                 acc.set(item, (acc.get(item)||0)+1))            return acc          }, new Map)          .entries()]          .reduce((acc, [item, repetitions]) =>             (repetitions == 1 && acc.push(item), acc), [])            console.log(getUniques(arr1, arr2)).as-console-wrapper {min-height:100%;}上述方法具有 O(n) 时间复杂度,这与您最初的尝试和您当前接受的答案(均具有 O(n²) 时间复杂度)相反。因此,它可能在大型阵列上执行得更快(任意数量的阵列,作为奖励)。

qq_笑_17

使用 _.difference(array, [values])来自lodash或者自己的解决方案:const diffArray = (arrayA, arrayB) => {    const output = []    const setA = new Set(arrayA);    arrayB.forEach((n) =>{       if(!setA.has(n)){         output.push(n)       }    })    const setB = new Set(arrayB);    arrayA.forEach(n =>{       if(!setB.has(n)){         output.push(n)       }    })    return output;}console.log(diffArray([1, 2, 3, 5, 6], [1, 2, 3, 4, 5])); //4, 6
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答