Javascript 取两个数组的差并生成一个新数组

Javascript 取两个数组的差并生成一个新数组,javascript,Javascript,我需要这个函数来比较两个数组,并返回一个新数组,该数组只包含两个数组都不通用的元素。我编写了以下代码: function diff(arr1, arr2) { var newArray = []; for (var i=0;i<arr1.length;i++){ for (var j=0;j<arr2.length;j++){ if (arr1[i]===arr2[j]){ arr1.splice(i,1); arr2

我需要这个函数来比较两个数组,并返回一个新数组,该数组只包含两个数组都不通用的元素。我编写了以下代码:

function diff(arr1, arr2) {

  var newArray = [];

  for (var i=0;i<arr1.length;i++){
    for (var j=0;j<arr2.length;j++){
      if (arr1[i]===arr2[j]){

        arr1.splice(i,1);
        arr2.splice(j,1);
      }
    }
  }
  newArray = arr1.concat(arr2);
  return newArray;
}

diff([1, 2, 3, 5], [1, 2, 3, 4, 5]);
功能差异(arr1、arr2){
var newArray=[];

对于(var i=0;i
.splice
会使数组发生变异,因此会干扰循环。代码的一个简单修复方法是按相反顺序迭代:

for (var i=arr1.length; i--;){
  for (var j=arr2.length; j--){

  }
}
但是,仍然存在这样一个问题:您拼接
arr1
的频率太高。
arr1
每次迭代只能拼接一次:

for (var i=arr1.length; i--;){
  var same = false;
  for (var j=arr2.length; j--;){
    if (arr1[i] === arr2[j]) {
      same = true;
      arr2.splice(j, 1);
      break;
    }
  }
  if (same) {
    arr1.splice(i, 1);
  }
}
功能差异(arr1、arr2){
对于(var i=arr1.length;i--;){
var-same=false;
对于(var j=arr2.length;j--;){
如果(arr1[i]==arr2[j]){
相同=正确;
arr2.拼接(j,1);
打破
}
}
如果(相同){
arr1.拼接(i,1);
}
}
返回arr1.concat(arr2);
}
log(diff([1,2,3,5],[1,2,3,4,5]);
您可以尝试:

function diff(arr1, arr2) {

    var tmp = [];
    var newArray = [];

    for (var i = 0; i < arr1.length; i++) {
        for (var j = 0; j < arr2.length; j++) {
            if (arr1[i] === arr2[j]) {
                arr1[i] = arr2[j] = null;
            }
        }
    }
    tmp = arr1.concat(arr2);
    for (var i = 0; i < tmp.length; i++) {
        if (tmp[i] !==null) {
            newArray.push(tmp[i]);
        }
    }
    return newArray;
}

console.log(diff([0,1,2], [1,2]));//output: [0]
功能差异(arr1、arr2){
var tmp=[];
var newArray=[];
对于(变量i=0;i
当您拼接阵列时,所有元素都会在其位置向下移动,这会使循环跳跃一步。例如,当它移除
0位置的
1
时,
2
移动到新的
0
部分,您已经检查过它是否跳过下一步。一个简单的修复方法是当y若要确保返回步骤,可以同时减小
i
j

  if (arr1[i]===arr2[j]) {
    arr1.splice(i,1);
    arr2.splice(j,1);
    i--; 
    j--;  
  }

对两个数组进行排序,从中删除重复项,合并两个数组,对获得的数组进行排序,然后从获得的数组中删除重复项

function getArraysDifference(a1, a2) {

    sortAndRemoveDuplicates(a1);
    sortAndRemoveDuplicates(a2);
    var outputArray = a1.concat(a2)
    sortAndRemoveDuplicates(outputArray);
    return outputArray; 

}

function sortAndRemoveDuplicates(inputArray) {

    inputArray.sort();
    var lastValue = inputArray[0];
    var i = 0;
    var currentValue;

    for (i = 1; i < inputArray.length; i++) {

        currentValue = inputArray[i];

        if (currentValue === lastValue) {
            inputArray.splice(i, 1);
            i--;
        } else {
            lastValue = currentValue;
        }

    }

}
函数getArraysDifference(a1、a2){ 排序和删除的副本(a1); sortAndRemoveDuplicates(a2); var outputArray=a1.concat(a2) SortandRemovedDuplicates(输出阵列); 返回输出阵列; } 函数排序和删除的副本(输入阵列){ inputArray.sort(); var lastValue=输入阵列[0]; var i=0; 无功电流值; 对于(i=1;i
最坏情况下的时间复杂度为O((N+M)log(N+M))。您尝试的解决方案可行,但时间复杂度为O(N*M)

编辑 事实证明,由于webkit(我没有在其他浏览器上进行研究)使用选择排序进行排序,因此该解决方案导致时间复杂度为O(NM)。
但是,在Java中,这种方法应该更快,因为引擎甚至可以达到O(N)来对相当短的数组进行排序,否则就只能使用O(N log(N))排序的复杂性。

设置一个临时对象。迭代两个数组。对于每个数组中的每个元素,如果该元素不是临时对象中的键,则在该对象中设置一个与该元素相等的键,值为
true
。如果已访问某个元素,则将其删除

最后,返回Object.keys(obj)以获得一个键数组

function differenceOfTwoArrays(arr1, arr2) {
  var obj = {};

  arr1.forEach(function(elem) {
    if (!obj[elem]) {
      obj[elem] = true;
    } else if (obj[elem]) {
      delete (obj[elem]);
    }
  });

  arr2.forEach(function(elem) {
    if(!obj[elem]) {
      obj[elem] = true;
    } else if (obj[elem]) {
      delete (obj[elem]);
    }
  });

  return Object.keys(obj);
}

与其他答案相比,代码更少:

function diff(arr1, arr2) {
  var newArray = [];
  for (var i=0;i<arr1.length;i++) {
    if (arr2.indexOf(arr1[i]) == -1) newArray.push(arr1[i]);
  }
  for (var i=0;i<arr2.length;i++){
    if (arr1.indexOf(arr2[i]) == -1) newArray.push(arr2[i]);
  }
  return newArray;
}
功能差异(arr1、arr2){
var newArray=[];
对于(var i=0;i

似乎这个答案在Chrome上是目前为止最快的,比Yang在Firefox上的速度要慢一些

将数组值转换为对象键可以加快速度:

function diff_dms2(arr1, arr2) {
  var newArray = [];
  var ob1 = { };
  var ob2 = { };
  for (var i=0; i<arr1.length; i++) ob1[arr1[i]] = true;
  for (var i=0; i<arr2.length; i++) ob2[arr2[i]] = true;
  for (var i=0;i<arr1.length;i++) {
    if (!ob2[arr1[i]]) newArray.push(arr1[i]);
  }
  for (var i=0;i<arr2.length;i++){
    if (!ob1[arr2[i]]) newArray.push(arr2[i]);
  } 
  return newArray;
}
功能差异dms2(arr1、arr2){
var newArray=[];
var ob1={};
var ob2={};
对于(var i=0;i这里有一个有趣的“参考”实现。它的目的不是为了特别快或高效,而是为了正确,并从代码中阐明算法,这有助于确保正确性。您可以编写“更好”的版本,并将其与此版本进行比较,以确保正确性。
“自动化测试是最好的测试。”:-)

它的功能与问题中所述完全相同:两个数组共有的元素(不一定是整数)将从两个数组中删除。这意味着一个数组中的重复项在另一个数组中找不到,保持不变

函数arrayDiff(array1,array2){
var r1=array1.slice();
var r2=array2.slice();
var r1Unique=[];//已知“唯一”值的收集器
while(!r1.every)函数(r1Obj){
var uniqueR1Obj=r2.every(函数r2Obj){
如果(r1Obj!==r2Obj){
return true;//到目前为止是唯一的,继续处理
}
//冲突:删除R2中对此对象的所有引用
var newR2=[];
r2.forEach(函数(oldR2Obj){
if(oldR2Obj!==r2Obj){
新r2.push(旧r2obj);
}
} );
r2=newR2;//开始在新的较小阵列上操作
return false;//唯一性丢失,bail
} );
if(uniqueR1Obj){
r1Unique.push(r1Obj);
}
//删除R1中对此对象的所有引用
var newR1=[];
r1.forEach(函数(oldR1Obj){
if(oldR1Obj!==r1Obj){
newR1.推送(oldR1Obj);
}
} );
r1=newR1;//开始在新的较小阵列上操作
return uniqueR1Obj;//如果仍然是唯一的,则继续处理,或者
} ) );
返回r1.concat(r1.concat(r2));
}
函数addTestResults(r1、r2){
变量s='arrayDiff(['+r1+'],['+r2+'])==['+arrayDiff(r1,r2)+']
; el=document.getElementById(“输出”); 如果(el!==null) el.innerHTML+=s; }
function diff_dms2(arr1, arr2) {
  var newArray = [];
  var ob1 = { };
  var ob2 = { };
  for (var i=0; i<arr1.length; i++) ob1[arr1[i]] = true;
  for (var i=0; i<arr2.length; i++) ob2[arr2[i]] = true;
  for (var i=0;i<arr1.length;i++) {
    if (!ob2[arr1[i]]) newArray.push(arr1[i]);
  }
  for (var i=0;i<arr2.length;i++){
    if (!ob1[arr2[i]]) newArray.push(arr2[i]);
  } 
  return newArray;
}