是否有一种方法可以在JavaScript中返回两个数组之间的差异?

例如:

var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];

// need ["c", "d"]

当前回答

**这将根据'type'参数为任意2个数组返回一个唯一值数组,或一个重复值数组,或一个非重复值数组(difference)。**

let json1 = ['one', 'two']
let json2 = ['one', 'two', 'three', 'four']

function uniq_n_shit (arr1, arr2, type) {

  let concat = arr1.concat(arr2)
  let set = [...new Set(concat)]

  if (!type || type === 'uniq' || type === 'unique') {

    return set

  } else if (type === 'duplicate') {

    concat = arr1.concat(arr2)
    return concat.filter(function (obj, index, self) {
      return index !== self.indexOf(obj)
    })

  } else if (type === 'not_duplicate') {

    let duplicates = concat.filter(function (obj, index, self) {
      return index !== self.indexOf(obj)
    })

    for (let r = 0; r < duplicates.length; r++) {
      let i = set.indexOf(duplicates[r]);
      if(i !== -1) {
        set.splice(i, 1);
      }
    }

    return set

  }
}

console.log(uniq_n_shit(json1, json2, null)) // => [ 'one', 'two', 'three', 'four' ]
console.log(uniq_n_shit(json1, json2, 'uniq')) // => [ 'one', 'two', 'three', 'four' ]
console.log(uniq_n_shit(json1, json2, 'duplicate')) // => [ 'one', 'two' ]
console.log(uniq_n_shit(json1, json2, 'not_duplicate')) // => [ 'three', 'four' ]

其他回答

简单地比较所有值,并返回数组与不重复的值。

var main = [9, '$', 'x', 'r', 3, 'A', '#', 0, 1];

var arr0 = ['Z', 9, 'e', '$', 'r'];
var arr1 = ['x', 'r', 3, 'A', '#'];
var arr2 = ['m', '#', 'a', 0, 'r'];
var arr3 = ['$', 1, 'n', '!', 'A'];


Array.prototype.diff = function(arrays) {
    var items = [].concat.apply(this, arguments);
    var diff = [].slice.call(items), i, l, x, pos;

    // go through all items
    for (x = 0, i = 0, l = items.length; i < l; x = 0, i++) {
        // find all positions
        while ((pos = diff.indexOf(items[i])) > -1) {
            // remove item + increase found count
            diff.splice(pos, 1) && x++;
        }
        // if item was found just once, put it back
        if (x === 1) diff.push(items[i]);
    }
    // get all not duplicated items
    return diff;
};

main.diff(arr0, arr1, arr2, arr3).join(''); // returns "Zeman!"

[].diff(main, arr0, arr1, arr2, arr3).join(''); // returns "Zeman!"

我在这里读到的答案有很多问题,使得它们在实际编程应用中价值有限。

First and foremost, you're going to want to have a way to control what it means for two items in the array to be "equal". The === comparison is not going to cut it if you're trying to figure out whether to update an array of objects based on an ID or something like that, which frankly is probably one of the most likely scenarios in which you will want a diff function. It also limits you to arrays of things that can be compared with the === operator, i.e. strings, ints, etc, and that's pretty much unacceptable for grown-ups.

其次,diff操作有三种状态结果:

在第一个数组中但不在第二个数组中的元素 两个数组共用的元素 在第二个数组中但不在第一个数组中的元素

我认为这意味着你需要不少于2个循环,但我愿意接受肮脏的技巧,如果有人知道如何将其减少到一个。

这里是我拼凑的一些东西,我想强调的是,我绝对不在乎它在旧版本的Microshaft浏览器中不起作用。如果您在IE这样的较差的编码环境中工作,那么您就可以自行修改它,使其在您无法满意的限制范围内工作。

Array.defaultValueComparison = function(a, b) {
    return (a === b);
};

Array.prototype.diff = function(arr, fnCompare) {

    // validate params

    if (!(arr instanceof Array))
        arr = [arr];

    fnCompare = fnCompare || Array.defaultValueComparison;

    var original = this, exists, storage, 
        result = { common: [], removed: [], inserted: [] };

    original.forEach(function(existingItem) {

        // Finds common elements and elements that 
        // do not exist in the original array

        exists = arr.some(function(newItem) {
            return fnCompare(existingItem, newItem);
        });

        storage = (exists) ? result.common : result.removed;
        storage.push(existingItem);

    });

    arr.forEach(function(newItem) {

        exists = original.some(function(existingItem) {
            return fnCompare(existingItem, newItem);
        });

        if (!exists)
            result.inserted.push(newItem);

    });

    return result;

};

要从另一个数组中减去一个数组,只需使用下面的代码片段:

var a1 = ['1','2','3','4','6'];
var a2 = ['3','4','5'];

var items = new Array();

items = jQuery.grep(a1,function (item) {
    return jQuery.inArray(item, a2) < 0;
});

它将返回['1,'2','6'],这些是第一个数组中不存在的项。

因此,根据您的问题示例,以下代码是准确的解决方案:

var array1 = ["test1", "test2","test3", "test4"];
var array2 = ["test1", "test2","test3","test4", "test5", "test6"];

var _array = new Array();

_array = jQuery.grep(array2, function (item) {
     return jQuery.inArray(item, array1) < 0;
});

以下是我使用的方法:

var newArr = a1.filter(function(elem) {
            return a2.indexOf(elem) === -1;
        }).concat( a2.filter(function(elem) {
            return a1.indexOf(elem) === -1;
        }));
console.log(newArr);

或者这个

var newArr = a1.concat(a2);
        function check(item) {
            if (a1.indexOf(item) === -1 || a2.indexOf(item) === -1) {
                return item;
            }
        }
        return newArr.filter(check);
function diffArray(arr1, arr2) {
  var newArr = arr1.concat(arr2);
  return newArr.filter(function(i){
    return newArr.indexOf(i) == newArr.lastIndexOf(i);
  });
}

这对我很有用