【问题标题】:Check if array of objects includes an object检查对象数组是否包含对象
【发布时间】:2020-06-07 07:50:33
【问题描述】:

我正在尝试检查对象数组是否包含对象。当数组中有一个具有相同值的对象并且对象ID无关紧要时,我希望它返回true。这就是我认为它会起作用的方式:

let arr = [{r:0, g:1}];
let obj = {r:0, g:1}

console.log(arr.includes(obj));

但它返回 false,我需要它返回 true。我是否必须使用 JSON.stringify() 将数组中的每个对象转换为字符串,而我正在搜索的对象如下:

let arr = [JSON.stringify({r: 0, g: 1})]
let obj = {r: 0, g: 1}

console.log(arr.includes(JSON.stringify(obj)));

还有其他更简单、更有效的方法来处理更多对象吗?

【问题讨论】:

  • objarr[0] 是内容相似的不同对象。如果它们引用同一个对象,它将返回 true:console.log(arr.includes(arr[0]));
  • 使用arr.some() (developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…) 并选择合适的策略来匹配对象。最简单的方法是在每个对象上都有一个唯一的标识符属性。您还可以使用对象相等性测试器功能。有许多提供此类功能的实用程序库,例如罗达什。

标签: javascript arrays node.js json


【解决方案1】:

您会得到false,因为对象是通过对该对象的引用进行比较的,而您有两个单独的对象实例。

Wile JSON.stringify 可能会起作用,请记住,属性的顺序不能保证,如果顺序不同,它可能会失败,因为你得到不同的字符串。

您可以检查id 属性或比较几个要匹配的属性,如果必须的话,您可以使用循环比较所有属性。

如果您有权访问对象的引用,则可以使用MapSet,它允许您存储和检查引用

const obj = {r:0, g:1};
const obj2 = {r:0, g:1};
const mySet = new Set();
// given the fact that you do have access to the object ref
mySet.add(obj);

const isObjInList = mySet.has(obj);
const isObj2InList = mySet.has(obj2);

console.log('is obj in list - ', isObjInList);
console.log('is obj2 in list - ', isObj2InList);

【讨论】:

    【解决方案2】:

    如果您更改其中一个对象的属性顺序,JSON.stringify 将无法按预期工作。

    您可以将.some 与来自lodash 的isEqual 结合使用(或其他替代方法)。或者你可以自己写,但要小心,有太多的边缘情况,这就是我推荐使用现有方法的原因。无需重新发明轮子。

    let arr = [JSON.stringify({r: 0, g: 1})]
    let obj = {g: 1, r: 0}
    
    console.log(arr.includes(JSON.stringify(obj)));
    
    let arr2 = [{r:0, g:1}];
    let obj2 = {g:1, r:0};
    
    console.log(arr2.some(item => _.isEqual(item, obj2)));
    console.log(_.some(arr2, item => _.isEqual(item, obj2))); // more canonical way
    <script src="https://cdn.jsdelivr.net/lodash/4/lodash.min.js"></script>

    【讨论】:

      【解决方案3】:

      我喜欢为此目的使用Set(),请阅读文档:

      Set 对象允许您存储任何类型的唯一值,无论是原始值还是对象引用。

      请看下面的例子:

      let obj = {r:0, g:1};
      const set = new Set();
      set.add(obj);
      
      console.log(set.has(obj));

      希望对你有帮助!

      【讨论】:

      • OP 想要的是匹配两个看起来相同但仍然是两个不同对象引用的对象。使用 Set 对该用例没有影响。
      【解决方案4】:

      您可以使用 JavaScript some() 方法来确定 JavaScript 数组是否包含对象。

      此方法测试数组中的至少一个元素是否通过了提供的函数实现的测试。这是一个演示其工作原理的示例:

       // An array of objects
          var persons = [{name: "Harry"}, {name: "Alice"}, {name: "Peter"}];
      
          // Find if the array contains an object by comparing the property value
          if(persons.some(person => person.name === "Peter")){
              alert("Object found inside the array.");
          } else{
              alert("Object not found.");
          }
      

      请注意,如果尝试使用indexOf() 方法(如persons.indexOf({name: "Harry"}))在数组中查找对象,它将不起作用(总是返回-1)。因为,即使它们看起来相同(即具有相同的属性和值),两个不同的对象也不相等。同样,两个不同的数组即使具有相同顺序的相同值也不相等。

      所有主流浏览器都支持some() 方法,例如Chrome、Firefox、IE(9 及以上)等。请参阅JavaScript ES6 Features 教程以了解有关箭头函数符号的更多信息。

      【讨论】:

        猜你喜欢
        • 2022-11-09
        • 2020-08-09
        • 1970-01-01
        • 1970-01-01
        • 2021-03-09
        • 2019-07-26
        • 2021-12-21
        • 2015-01-24
        • 2015-01-22
        相关资源
        最近更新 更多