Сравнение двух массивов в Javascript

У меня есть два массива в Javascript, которые в настоящее время выглядят так, но обновляются HTTP-запросами (node):

var x = [[292,"2349","902103","9"],[3289,"93829","092","920238"]]
var y = [[292,"2349","902103","9"],[322,"93829","092","920238"],[924,"9320","8932","4329"]]

Я хочу сравнить эти массивы, так что если массив внутри y, который не находится в x, он будет сохранен в новый массив - z. Обратите внимание, что иногда порядок массивов внутри массивов будет меняться, но мне не хотелось бы, чтобы это повлияло на результат.

Если массив внутри x, который не находится в y, однако, он не должен быть сохранен в z.

Я читал разницу в массиве JavaScript и смог реплицировать это, но если массив x не показан в y, он печатается на z. Мне интересно, возможно ли, чтобы это не было сохранено, только разные элементы в y?

Ответ 1

Используйте функцию более высокого порядка, которая принимает массив (который изменяется с каждой итерацией y) и возвращает новую функцию, которая работает с каждым элементом (вложенным массивом) в some. Он возвращает true, если массивы содержат одни и те же элементы независимо от порядка.

function matches(outer) {
  return function (el) {
    if (outer.length !== el.length) return false;
    return el.every(function (x) {
      return outer.indexOf(x) > -1;
    });
  }
}

Перейдите к y и верните список массивов, которые не находятся в x.

function finder(x, y) {
  return y.filter(function (el) {
    return !x.some(matches(el));
  });
}

finder(x, y);

DEMO

Ответ 2

Вы можете использовать эту функцию arrayDiff.

Он принимает два массива (A и B) и возвращает массив всех элементов, которые находятся в первом массиве, а не во втором (A\B), при удалении любых дубликатов. Два элемента массива равны, если их сериализация JSON одинакова.

var x = [[292,"2349","902103","9"],[3289,"93829","092","920238"]];
var y = [[292,"2349","902103","9"],[322,"93829","092","920238"],[924,"9320","8932","4329"]];

var z = arrayDiff(y, x);

// z is [[322,"93829","092","920238"],[924,"9320","8932","4329"]]

// arrayDiff :: [a], [a] -> [a]
function arrayDiff(a1, a2) {
    let a1Set = toStringSet(a1),
        a2Set = toStringSet(a2);

    return Array.from(a1Set)
                .filter(jsonStr => !a2Set.has(jsonStr))
                .map(JSON.parse);

    // toStringSet :: [a] -> Set<String>
    function toStringSet(arr) {
        return new Set(arr.map(JSON.stringify));
    }
}

Ответ 3

Это должно работать, даже если порядок во внутренних массивах отличается.
Я предполагаю, что у вас будут только цифры и строки, и вы не ожидаете строгого сравнения между ними.

var x = [[292,"2349","902103","9"],[3289,"93829","092","920238"]];
var y = [[292,"2349","902103","9"],[322,"93829","092","920238"],[924,"9320","8932","4329"]];

// this will do y \ x
var z = arrDiff(y, x);
console.log(z);


function arrDiff(arr1, arr2) {
  var rez = [];

  for (var i = 0; i < arr1.length; i++) {
    if ( ! contains(arr2, arr1[i])) {
      rez.push(arr1[i]);
    }
  }

  return rez;
}

function contains(arr, x) {
  x = x.slice().sort().toString();
  for (var i = 0; i < arr.length; i++) {
    // compare current item with the one we are searching for        
    if (x === arr[i].slice().sort().toString()) {
      return true;
    }
  }

  return false;
}

Ответ 4

Попробуйте следующее:

function getArraysDiff(arr1, arr2) {
   var x = arr1.map(function(a) { return a.join("") });
   var y = arr2.map(function(a) { return a.join("") });
   var z = [];

   for ( var i = 0, l = arr1.length; i < l; i++ ) {
      if ( y.indexOf(x[i]) == -1 ) {
        z.push(arr1[i])
      }
   }

   return z;
}

Или это:

x.filter((function(y) {
    return function(x) {
        return y.indexOf(x.join("")) > -1;
    }
}( y.map(function(y) { return y.join("") }) )))

Ответ 5

Вы можете использовать Array.prototype.forEach(), Array.prototype.every(), Array.prototype.map(), Array.prototype.indexOf(), JSON.stringify(), JSON.parse()

var z = [];
y.forEach(function(val, key) {
  var curr = JSON.stringify(val);
  var match = x.every(function(v, k) {
    return JSON.stringify(v) !== curr
  });
  if (match && z.indexOf(curr) == -1) z.push(curr)
});

z = z.map(JSON.parse);

var x = [
  [292, "2349", "902103", "9"],
  [3289, "93829", "092", "920238"]
];
var y = [
  [292, "2349", "902103", "9"],
  [322, "93829", "092", "920238"],
  [924, "9320", "8932", "4329"]
];

var z = [];
y.forEach(function(val, key) {
  var curr = JSON.stringify(val);
  var match = x.every(function(v, k) {
    return JSON.stringify(v) !== curr
  });
  if (match && z.indexOf(curr) == -1) z.push(curr)
});

z = z.map(JSON.parse);

console.log(z);

document.querySelector("pre").textContent = JSON.stringify(z, null, 2)
<pre></pre>

Ответ 6

У вас есть 2 массива:

var x = [[292,"2349","902103","9"],[3289,"93829","092","920238"]];
var y = [[292,"2349","902103","9"],[322,"93829","092","920238"],[924,"9320","8932","4329"]];

Чтобы создать массив Z, вам понадобится следующая функция:

function createZ(){
  var i,j,k=0,z=[],p=x;
  for(j=0;j<y.length;j++){
    for(i=0;i<p.length;i++){
      if(y[j][0]===p[i][0] && y[j][1]===p[i][1] && y[j][2]===p[i][2] && y[j][3]===p[i][3]){
        p.splice(i,1); break;
      } else {
        z[k++]=y[j]; console.log((y[j][0]===p[i][0])+" "+i+","+j);
      }
    }
  }
  return z;
}

Обратите внимание, что createZ() также выводит i, j соответствующей записи на консоль.