Javascript数组——检查两个对象数组以获取相同的内容,忽略顺序

时间:2022-10-31 12:14:35

I have two JavaScript arrays (A and B) that contain objects that I created. I want to check that all the objects in array A are contained in array B, but not necessarily in the same order.

我有两个JavaScript数组(A和B),它们包含我创建的对象。我要检查数组A中的所有对象是否都包含在数组B中,但顺序不一定相同。

What is the best way to do this?

最好的方法是什么?

Edit:

编辑:

They are all actual objects, not primitives, so I will need to compare their contents and structure as well (maybe using something like JSON.stringify).

它们都是实际的对象,而不是原语,因此我还需要比较它们的内容和结构(可能使用JSON.stringify之类的东西)。

I want to do this because I'm learning Test-Driven Development, and I want to test functions that return lists of objects. I need to test whether the returned lists have the expected objects in them or not (order doesn't matter in this case).

我想这样做是因为我在学习测试驱动开发,我想测试返回对象列表的函数。我需要测试返回的列表中是否包含预期的对象(在这种情况下,顺序无关紧要)。

4 个解决方案

#1


2  

Usage: isEqArrays(arr1, arr2)

用法:isEqArrays(arr1 arr2)

//
// Array comparsion
//

function inArray(array, el) {
  for ( var i = array.length; i--; ) {
    if ( array[i] === el ) return true;
  }
  return false;
}

function isEqArrays(arr1, arr2) {
  if ( arr1.length !== arr2.length ) {
    return false;
  }
  for ( var i = arr1.length; i--; ) {
    if ( !inArray( arr2, arr1[i] ) ) {
      return false;
    }
  }
  return true;
}

#2


3  

If the duplicates do not matter, you can make an one-liner by using lodash. Look if the difference between two arrays is empty.

如果复制不重要,您可以使用lodash创建一个一行。看看两个数组之间的差异是否为空。

if (_(array).difference(otherArray).isEmpty()) {
    // is equal ignoring order and duplicates
}

console.log(_([1,2,3]).difference([2,3,1]).isEmpty()) // -> true
console.log(_([1,2,3,3]).difference([2,3,1,1]).isEmpty()) // -> also true

#3


1  

This is probably the simplest method if not the slowest.

这可能是最简单的方法,如果不是最慢的话。

var o = { PropA: 1, PropB: 2 };
var a = [1, 2, 3, 4, o];
var b = [2, 3, 4, 1];

var c = a.filter(function(value, index, obj) {
    return b.indexOf(value) > -1;
});

if (c.length !== a.length) {
    throw new Error("Array b is missing some elements!");
}

indexOf will only check that they refer to the same object. If you want to check value equivalence you will have to do a deep compare of the properties or use JSON.stringify as you mention in your question.

indexOf只检查它们是否引用相同的对象。如果要检查值等价性,就必须对属性进行深入的比较,或者使用JSON。在你的问题中,你提到了stringify。

#4


0  

With ES6 you could use every and some (and length).

有了ES6,你可以使用所有的(和长度)。

let A = [1, 2, 3];
let B = [2, 3, 1];

// all objects in A are contained in B (A ⊆ B)
// you can compare a <-> b however you'd like (here just `a === b`)
let AsubB = A.every(a => B.some(b => a === b));

// A and B are the same length
let sameLength = A.length === B.length;

// their contents are as equal as previously tested:
let equal = AsubB && sameLength;

#1


2  

Usage: isEqArrays(arr1, arr2)

用法:isEqArrays(arr1 arr2)

//
// Array comparsion
//

function inArray(array, el) {
  for ( var i = array.length; i--; ) {
    if ( array[i] === el ) return true;
  }
  return false;
}

function isEqArrays(arr1, arr2) {
  if ( arr1.length !== arr2.length ) {
    return false;
  }
  for ( var i = arr1.length; i--; ) {
    if ( !inArray( arr2, arr1[i] ) ) {
      return false;
    }
  }
  return true;
}

#2


3  

If the duplicates do not matter, you can make an one-liner by using lodash. Look if the difference between two arrays is empty.

如果复制不重要,您可以使用lodash创建一个一行。看看两个数组之间的差异是否为空。

if (_(array).difference(otherArray).isEmpty()) {
    // is equal ignoring order and duplicates
}

console.log(_([1,2,3]).difference([2,3,1]).isEmpty()) // -> true
console.log(_([1,2,3,3]).difference([2,3,1,1]).isEmpty()) // -> also true

#3


1  

This is probably the simplest method if not the slowest.

这可能是最简单的方法,如果不是最慢的话。

var o = { PropA: 1, PropB: 2 };
var a = [1, 2, 3, 4, o];
var b = [2, 3, 4, 1];

var c = a.filter(function(value, index, obj) {
    return b.indexOf(value) > -1;
});

if (c.length !== a.length) {
    throw new Error("Array b is missing some elements!");
}

indexOf will only check that they refer to the same object. If you want to check value equivalence you will have to do a deep compare of the properties or use JSON.stringify as you mention in your question.

indexOf只检查它们是否引用相同的对象。如果要检查值等价性,就必须对属性进行深入的比较,或者使用JSON。在你的问题中,你提到了stringify。

#4


0  

With ES6 you could use every and some (and length).

有了ES6,你可以使用所有的(和长度)。

let A = [1, 2, 3];
let B = [2, 3, 1];

// all objects in A are contained in B (A ⊆ B)
// you can compare a <-> b however you'd like (here just `a === b`)
let AsubB = A.every(a => B.some(b => a === b));

// A and B are the same length
let sameLength = A.length === B.length;

// their contents are as equal as previously tested:
let equal = AsubB && sameLength;