如何使用数组包含函数检查对象数组中的对象是否相等?

How can I check object equality in object array with using array includes function?

提问人:midstack 提问时间:6/20/2019 最后编辑:arjntmidstack 更新时间:6/20/2019 访问量:100

问:

我想检查数组是否具有作为参数提供给 js includes 函数的对象。例如:

let arr = [
    {'name': 'max', 'age': '20'},
    {'name': 'max', 'age': '21'},
    {'name': 'jane', 'age': '22'}];
console.log(arr.includes({'name': 'max', 'age': '21'})); // FALSE

这给了我“虚假”的价值。如何在没有for循环均衡器的情况下检查对象数组中的对象是否相等。

JavaScript 数组对象 相等

评论


答:

3赞 sjahan 6/20/2019 #1

你不能这样做,因为你没有处理相等性检查,并且对象是不同的,因此,没有任何匹配。includes

要做你想做的事,你可以使用 or !somefind

let arr = [
    {'name': 'max', 'age': '20'},
    {'name': 'max', 'age': '21'},
    {'name': 'jane', 'age': '22'}
];

console.log(arr.some(({name, age}) => name === 'max' && age === '21'));
console.log(!!arr.find(({name, age}) => name === 'max' && age === '21'));

请注意,返回对象,我已添加以打印布尔结果,但这不一定是强制性的。find!!

评论

1赞 arjnt 6/20/2019
如果你知道你的对象的结构,那么你就可以继续使用sjahan的解决方案。
1赞 sjahan 6/20/2019
作为参数中的函数,您可以轻松实现任何您想要/需要的“相等性检查函数”。虽然,在不知道你处理/比较什么的情况下工作可能会产生性能成本。拥有一个深入到两个对象的“通用”比较功能很酷,但可能很昂贵。如果这不能回答您的问题,请告诉我,我会删除它。somefind
2赞 arjnt 6/20/2019 #2

这是实现相同结果的另一种方法:

如果对象的结构以前不是很清楚,即当它们动态变化时,从 API 或其他东西,那么您可以使用以下解决方案

let arr = [
    {'name': 'max', 'age': '20'},
    {'name': 'max', 'age': '21'},
    {'name': 'jane', 'age': '22'}
];


let x =   {'name': 'max', 'age': '20'};
let result =arr.map( ele => JSON.stringify(ele)).includes(JSON.stringify(x));
console.log(result)

上述解决方案也适用于嵌套对象。

注意该解决方案有两个注意事项

  1. 只要您的键的顺序在整个数组中以及在您希望比较的对象中保持不变,它就会起作用x
  2. 如果对象中的嵌套过多,那么它会非常慢。我不会向任何关心性能的人推荐 JSON.stringify。

编辑 1

  1. 不适用于圆形结构

评论

1赞 darklightcode 6/20/2019
您可以添加: 3.不适用于圆形结构
2赞 briosheje 6/20/2019 #3

这是一个依赖于两者的选项,以确保所有传递的对都存在并在目标数组内匹配。 这也将忽略键的顺序,并接受动态输入。.some.entrieskey-value

此示例假定,如果提供的密钥较少,则仅检查这些密钥。例如,检查 only 将返回 true。{'name': 'max'}

let arr = [
    {'name': 'max', 'age': '20'},
    {'name': 'max', 'age': '21'},
    {'name': 'jane', 'age': '22'}];

function includedInArray(lookups, _arr) {
  // Ensure every lookup match.
  return _arr.some(i => {
    // Loop key-value pairs.
    return Object.entries(lookups).every(([key, value]) => {
      return i[key] === value;
    });
  });
};

console.log(includedInArray({
  'name': 'max',
  'age': '21'
 }, arr)); // should return true.
 
 console.log(includedInArray({
  'age': '21',
  'name': 'max'
 }, arr)); // should return true.
 
 console.log(includedInArray({
  'age': '55',
  'name': 'max'
 }, arr)); // should return false.
 
 console.log(includedInArray({
  'name': 'max'
 }, arr)); // should return true.

3赞 georg 6/20/2019 #4

你可以编写一个泛型函数,如

let matches = flt => x => Object.keys(flt).every(k => flt[k] === x[k]);

然后

arr.some(matches({'name': 'max', 'age': '21'}))

这执行了浅层的、部分的比较。如果您需要其他模式,例如完整和/或深度比较,这将更加棘手。在这种情况下,我建议使用 lodash (, )。_.isMatching_.isEqual

评论

0赞 briosheje 6/20/2019
哼。我比我的更喜欢这个,干得好。有什么理由使用代替吗?我的意思是,我很确定它会是一样的,只是想知道。keysentries
0赞 georg 6/20/2019
@briosheje:没有特别的原因,只是支持范围稍广。keys