在javascript中找到多个数组中的对称差异/唯一元素

时间:2015-05-26 20:53:39

标签: javascript arrays

嗨,我正在努力解决这个问题。如何创建一个将任意数量的数组作为参数的javascript函数,然后返回仅出现在其中一个数组中的元素数组。将删除多个阵列中显示的所有项目。没有解决方案,怀疑我没有以正确的方式接近它,难倒!

编辑:另一个问题是在一个数组中消除重复值,我需要比较x个独立的数组并返回数组之间没有重复的值。所以([5,6,7],[5,8,9])返回[6,7,8,9]。

function sym(args) {
  var ans = [];


  for(var i =0;i<arguments.length;i++){
    var tempArr = arguments[i].filter(function(el){
      var filtTrue = false;
       for(var j = 0;j<arguments.length;j++){
         if(Array.isArray(arguments[j]) && arguments[j] !== arguments[i]){
           if(arguments[j].indexOf(el) === -1){
             filtTrue = true;
              }}
        }
           return filtTrue;
          });
           ans = ans.concat(tempArr);
  }



    return ans;
  }

3 个答案:

答案 0 :(得分:2)

这是一种方法。这里的想法是你创建一个地图来保存数组中所有项目的计数。然后循环遍历每个数组,在地图中查找每个值,如果找到,则增加其计数。如果未找到,则将计数设置为1.然后,完成所有数组后,您将收集任何计数为1的项目。

如果某个项目在同一个数组中出现多次,但在任何其他数组中不出现,则您没有具体说明该怎么做。第一个解决方案将不包括该项目(因为它检测到重复项)。如果这是一个问题,可以调整(稍微复杂一点)以允许该项目(请参阅下面的第二个代码块以实现该实现)。

function sym(/* pass one or more arrays here */) {
    var ans = [], cnts = {};

    //count all items in the array
    for (var i = 0; i < arguments.length; i++){
        arguments[i].forEach(function(item) {
            if (cnts.hasOwnProperty(item)) {
                // increase cnt
                ++cnts[item].cnt;
            } else {
                // initalize cnt and value
                cnts[item] = {cnt: 1, val: item};
            }
        });
    }
    for (var item in cnts) {
        if (cnts.hasOwnProperty(item) && cnts[item].cnt === 1) {
            ans.push(cnts[item].val);
        }
    }

    return ans;
}

如果你想在一个数组中包含多次出现但在任何其他数组中不存在的项目,那么你可以使用这个稍微复杂的改编:

function sym(/* pass one or more arrays here */) {
    var ans = [], cnts = {}, currentMap;

    //count all items in the array
    for (var i = 0; i < arguments.length; i++){
        currentMap = {};
        arguments[i].forEach(function(item) {
            // if we haven't already counted this item in this array
            if (!currentMap.hasOwnProperty(item)) {
                if (cnts.hasOwnProperty(item)) {
                    // increase cnt
                    ++cnts[item].cnt;
                } else {
                    // initalize cnt and value
                    cnts[item] = {cnt: 1, val: item};
                }
            }
            // keep track of whethere we've already counted this item in this array
            currentMap[item] = true;
        });
    }
    // output all items that have a cnt of 1
    for (var item in cnts) {
        if (cnts.hasOwnProperty(item) && cnts[item].cnt === 1) {
            ans.push(cnts[item].val);
        }
    }

    return ans;
}

工作演示:http://jsfiddle.net/jfriend00/bete5k3n/

答案 1 :(得分:1)

我知道这种情况可能会迟到,但这是另一种方法。也许不是最严谨的,但肯定是有创意的。方法Array.symmetricDifference()需要任意数量的参数,并返回这些参数的对称差异。

Array.prototype.symmetricDifference = function() {
  var args = [];

  // copy arguments into a real array and get rid of duplicates with filter
  for(var i = 0; i < arguments.length; i++) {
    args[i] = arguments[i];
    args[i] = args[i].filter(function(item, pos, self) {
      return self.indexOf(item) == pos;
    });
  }
  var diff = args[0];

  // iterate through every arguments in args.
  // concatenate the first two arguments to form a new set.
  // now every number in this new set that was contained in both arguments
  // from before will be contained at least twice in this new set.
  for(var j = 1; j < args.length; j++) {
    //sort the new set so that duplicates are next to each other.
    diff = diff.concat(args[j]).sort();
    var index = 0;

    // now iterate through the new set and delete both duplicates if you
    // find any. Otherwise proceed to the next index.
    while(index < diff.length) {
      // if duplicate is found delete both, otherwise look at next index.
      diff[index] === diff[index + 1] ? diff.splice(index, 2) : index++;
    }
  }
  return diff;
};

您可以在任何阵列上调用该方法或创建一个新方法并在其上调用它,例如:

// take any number of arrays
var a = [3, 3, 3, 2, 5];
var b = [2, 1, 5, 7];
var c = [3, 4, 6, 6];
var d = [1, 2, 3];
var e = [5, 3, 9, 8];
var f = [1];

// invoke the method on "solution" with any number of arguments
// and store it in solution.
var solution = solution.symmetricDifference(a,b,c,d,e,f);

console.log(solution); // [1, 2, 4, 5, 6, 7, 8, 9]

我希望这有帮助!

答案 2 :(得分:0)

在多个数组中查找唯一项目

function uniqueItemsInArrays(...args){
  let allItems = [];
  allItems = allItems.concat(...args)

  return allItems.filter(function(item, pos, self) {
         return self.indexOf(item) === pos && self.indexOf(item,pos+1) === -1;
  });
}

uniqueItemsInArrays( [1, 5, 1, 8, 1, 2],
                         [2, 2, 9, 3, 5],
                         [1, 4, 7, 6] );

上面的代码使用ES6 rest参数来访问作为参数传递的所有数组。然后使用concat()函数,我将所有单个数组连接到一个数组。最后,过滤函数已用于识别和返回此数组中的唯一项。这里的逻辑是找出当前项的第一个索引,如果第一个索引没有更多的出现,那么我们返回该项。