简体   繁体   English

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

[英]For two arrays find items that are present in one array only (symmetric difference)

I need to compare two arrays and return a new array with any items only found in one of the two given arrays, but not both.我需要比较两个数组并返回一个新数组,其中包含仅在两个给定数组之一中找到的任何项目,但不能同时在这两个数组中找到。 In other words, return the symmetric difference of the two arrays.换句话说,返回两个数组的对称差。 My algorithm consists of using the map() method on the first array and compare each of element of that array with the elements of the second array using every().我的算法包括在第一个数组上使用 map() 方法,并使用 every() 将该数组的每个元素与第二个数组的元素进行比较。 If this method returns true, the element gets returned on the block level of map (which will eventually add it to the returned array) if not it's discarded.如果此方法返回 true,则元素将在 map 的块级别返回(最终会将其添加到返回的数组中),否则将被丢弃。 I'm not sure why my code is not working.我不确定为什么我的代码不起作用。 This is an example of a wrong output using my code:这是使用我的代码的错误输出示例:

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]));

This is the wrong output: [ undefined, undefined, undefined, undefined ]这是错误的输出:[ undefined, undefined, undefined, undefined ]

The expected output is : [4]预期输出是:[4]

Your approach iterates the first array and because of using map along with the check for the value, you get undefined for every element of arr1 .您的方法迭代第一个数组,并且由于使用map以及检查值,因此您对arr1每个元素都未定义。

If you take filter and the other array as well, you could get the wanted result.如果您同时使用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]));

Another approach takes an array of all values of both arrays and filter by checking if the value is not included in both arrays.另一种方法采用两个数组的所有值的数组,并通过检查该值是否未包含在两个数组中来进行过滤。

 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]));

Use _.difference(array, [values])使用 _.difference(array, [values])

from lodash来自lodash

or或者

own solution :自己的解决方案:

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

This algorithm works even when numbers appear multiple times in both arrays.即使数字在两个数组中多次出现,该算法也能工作。

It uses a Map created from the items of both arrays.它使用从两个数组的项目创建的 Map。 The map contains the item as the key, and the value is the amount of times it's found in the 1st array - the number of times it's found it the 2nd array.地图包含作为键的项目,值是它在第一个数组中找到的次数 - 在第二个数组中找到它的次数。

After creating the Map, it's converted to an array of [item, count].创建 Map 后,将其转换为 [item, count] 数组。 The array is then filtered, and all items with a count of 0 are removed (they exist equally in both arrays), and then we map the array to an array of items.然后对数组进行过滤,并删除所有计数为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]));

Your function returns elements of the first array that are not present in the second array.您的函数返回第一个数组中不存在于第二个数组中的元素。

Its return is explained by the fact that .map() returns the array of exact same size as your input ( arr1 ), but since all items of arr1 are present in arr2 you don't enter if( -statement body hence undefined is getting returned.它的返回是通过.map()返回与输入( arr1 )大小完全相同的数组来解释的,但是由于arr1所有项目都存在于arr2您不输入if( -statement body 因此undefined正在获取回来。

If your intention was to return items that are present in one array only (regardless of the order they're passed in), you may leverage the Map object together with Array.prototype.reduce() :如果您的意图是仅返回存在于一个数组中的项目(无论它们传入的顺序如何),您可以将Map对象与Array.prototype.reduce()一起使用:

  • combine arrays-arguments into common array of arrays将数组参数组合成公共数组数组
  • loop through those inner arrays with .reduce() , building up the Map , showing how many times each item is seen within combined array使用.reduce()循环遍历这些内部数组,构建Map ,显示每个项目在组合数组中出现的次数
  • for each item of combined array remove duplicates and increment respective counter对于组合数组的每个项目,删除重复项并增加相应的计数器
  • spread resulting Map into .entries() and .filter() those to find out uniques将生成的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%;}

Above approach is of O(n)-time complexity, as opposed to your initial attempt and the answer you have currently accepted (both having O(n²)-time complexity).上述方法的时间复杂度为 O(n),而不是您的初始尝试和您目前接受的答案(两者都具有 O(n²) 时间复杂度)。 As a result it may perform much faster on large arrays (arbitrary number of arrays, as a bonus).因此,它可以在大的阵列(阵列中的任意数量,作为奖金)快得多执行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM