如何判断对象是否在数组中

IT技术 javascript
2021-02-06 16:53:26

我需要确定一个对象是否已经存在于 javascript 的数组中。

例如(虚拟代码):

var carBrands = [];

var car1 = {name:'ford'};
var car2 = {name:'lexus'};
var car3 = {name:'maserati'};
var car4 = {name:'ford'};

carBrands.push(car1);
carBrands.push(car2);
carBrands.push(car3);
carBrands.push(car4);

现在“carBrands”数组包含所有实例。我现在正在寻找一种快速解决方案来检查 car1、car2、car3 或 car4 的实例是否已经在 carBrands 数组中。

例如:

var contains =  carBrands.Contains(car1); //<--- returns bool.

car1 和 car4 包含相同的数据,但它们是不同的实例,它们应该被测试为不相等。

我是否在创建时向对象添加了哈希之类的东西?或者在 Javascript 中有更快的方法来做到这一点。

我在这里寻找最快的解决方案,如果脏,所以它必须是 ;) 在我的应用程序中,它必须处理大约 10000 个实例。

没有jQuery

6个回答

使用这样的东西:

function containsObject(obj, list) {
    var i;
    for (i = 0; i < list.length; i++) {
        if (list[i] === obj) {
            return true;
        }
    }

    return false;
}

在这种情况下,containsObject(car4, carBrands)是真的。删除carBrands.push(car4);调用,它将返回 false。如果您以后扩展到使用对象来存储这些其他汽车对象而不是使用数组,您可以使用类似这样的东西:

function containsObject(obj, list) {
    var x;
    for (x in list) {
        if (list.hasOwnProperty(x) && list[x] === obj) {
            return true;
        }
    }

    return false;
}

这种方法也适用于数组,但在数组上使用时,它会比第一个选项慢一点。

@RobB 是的,看起来我犯了一个复制粘贴错误——var i应该是var x. 已修复,感谢您指出这一点。
2021-03-18 16:53:26
应该在 i 或 x 之前添加一个 var,例如:for (var x in list)
2021-03-23 16:53:26
@MartínNieva 可能是因为您要查找的对象不在列表中,而是一个完全相同的不同对象。在这种情况下,使用 lodashisEqual()比滥用序列化更可取。(事实上​​,使用 lodash,整个解决方案变成了一个单行,结合_.some_.isEqual: _.some(list, v => _.isEqual(v, o))。)
2021-03-27 16:53:26
它应该是 JSON.stringify(list[i]) === JSON.stringify(obj) 而不是 list[i] === obj
2021-03-29 16:53:26
+1。我的回答没有抓住重点。这是正确的。(作为旁注,您可以完全按照 OP 所做的扩展 Array.prototype)
2021-04-06 16:53:26

为什么不使用javascript 数组indexOf方法?

看看这个:MDN indexOf Arrays

简单地做:

carBrands.indexOf(car1);

它将返回 car1 的索引(数组中的位置)。如果在数组中找不到 car1,它将返回 -1。

http://jsfiddle.net/Fraximus/r154cd9o

编辑:请注意,在问题中,要求是检查数组中引用相同对象,而不是新对象即使新对象的内容与数组中的对象相同,它仍然是不同的对象。正如评论中提到的,对象在 JS 中是通过引用传递的,并且同一个对象可以在多个结构中多次存在。
如果您想创建一个新对象并检查数组是否包含与您的新对象相同的对象,则此答案将不起作用(下面 Julien 的小提琴),如果您想检查数组中是否存在相同的对象,则此答案将工作。在此处和评论中查看小提琴。

当您尝试在数组中查找对象时,indexOf 总是返回 -1...这里的小例子:jsfiddle.net/7B7dQ/1
2021-03-13 16:53:26
男士们,在这个问题中,OP 想要类似carBrands.Contains(car1). 如果你做 carBrands.indexOf(car1),它会起作用。看看这个:jsfiddle.net/Fraximus/r154cd9o
2021-03-20 16:53:26
请记住,JS 中的对象是通过引用传递的。这意味着具有相同属性和相同值的两个对象不是同一个对象这也意味着一个对象实际上可以同时存在于多个数组中示例:jsfiddle.net/7B7dQ/33
2021-03-20 16:53:26
在 Julien 的小提琴中,它不起作用,因为它是一个新对象,即使它们是相同的。
2021-03-23 16:53:26
如果它显然不起作用,为什么会有 40 个赞成票?
2021-04-01 16:53:26

最近被 FP 错误所困扰,阅读了许多关于函数范式与 Javascript 完美契合的精彩描述

为了完整起见,我复制了代码并建议了两种可以在功能上完成的方法。

    var carBrands = [];

  var car1 = {name:'ford'};
  var car2 = {name:'lexus'};
  var car3 = {name:'maserati'};
  var car4 = {name:'ford'};
  var car5 = {name:'toyota'};

  carBrands.push(car1);
  carBrands.push(car2);
  carBrands.push(car3);
  carBrands.push(car4);

  // ES6 approach which uses the includes method (Chrome47+, Firefox43+)

  carBrands.includes(car1) // -> true
  carBrands.includes(car5) // -> false

如果您需要支持旧浏览器使用 polyfill,IE9+ 和 Edge 似乎不支持它。位于MSDN 页面的 polyfill 部分

或者,我想向cdhowie提出更新的答案

// ES2015 syntax
function containsObject(obj, list) {

    return list.some(function(elem) {
      return elem === obj
    })
}

// or ES6+ syntax with cool fat arrows
function containsObject(obj, list) {

    return list.some(elem => elem === obj)
}
@PrasanthGanesan carBrands 是一个对象数组,在这种情况下,其形状为“名称”键和汽车品牌类型值作为字符串。如果您不将 var car6 对象推送到数组中,include 方法确实会返回 false,如果将其推送到数组中,它将返回 true。参见我的 jsbin 示例 - jsbin.com/xeluyizaze/edit?js,console
2021-03-30 16:53:26
当我添加var car6 = {name:'ford'};到您的第一个解决方案并尝试时carBrands.includes(car6),它返回 false。你能解释一下吗?
2021-04-09 16:53:26

您可以使用jQuery 的 grep方法:

$.grep(carBrands, function(obj) { return obj.name == "ford"; });

但是当您没有指定 jQuery 时,您可以只对函数进行派生。从源代码:

function grepArray( elems, callback, inv ) {  
    var ret = [];  

    // Go through the array, only saving the items  
    // that pass the validator function  
    for ( var i = 0, length = elems.length; i < length; i++ ) {  
        if ( !inv !== !callback( elems[ i ], i ) ) {  
            ret.push( elems[ i ] );  
        }  
    }  

    return ret;  
}  

grepArray(carBrands, function(obj) { return obj.name == "ford"; });
什么是inv?它在哪里使用?
2021-03-25 16:53:26

尝试 Array.prototype.some()

MDN Array.prototype.some


    function isBiggerThan10(element, index, array) {
      return element > 10;
    }
    [2, 5, 8, 1, 4].some(isBiggerThan10);  // false
    [12, 5, 8, 1, 4].some(isBiggerThan10); // true