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

如(dummycode):

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数组中。

eg:

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

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

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

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

没有jquery


当前回答

可以这样说:

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。如果你后来扩展到使用对象来存储这些其他car对象,而不是使用数组,你可以使用这样的东西:

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

    return false;
}

这种方法也适用于数组,但是当用于数组时,它会比第一种方法慢一些。

其他回答

你可以使用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"; });

试试这个, 可以使用JavaScript的some()方法来确定JavaScript数组是否包含对象。

<script>
// 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.");
}
</script>

你可以尝试基于属性对数组进行排序,如下所示:

carBrands = carBrands.sort(function(x,y){
  return (x == y) ? 0 : (x > y) ? 1 : -1;
});

然后您可以使用迭代例程来检查是否

carBrands[Math.floor(carBrands.length/2)] 
// change carBrands.length to a var that keeps 
// getting divided by 2 until result is the target 
// or no valid target exists

大于或小于目标,等等,这将让您快速遍历数组以查找对象是否存在。

我使用下划线javascript库来调整这个问题。

function containsObject(obj, list) {
 var res = _.find(list, function(val){ return _.isEqual(obj, val)});
 return (_.isObject(res))? true:false;
}

关于上面例子中使用的下划线函数,请参考underscore.js文档。

注意:这不是一个纯javascript解决方案。为了教育目的而共享。

编辑05/18/2022

使用ES6最简单的方法:

const arrayContainsObject = <T extends Record<string, unknown>>(array: T[], object: T) => {
  return array.some(item => Object.keys(item).every(key => item[key] === object[key]))
}

像这样使用:

const arr = [{
  prop1: 'value1',
  prop2: 'value2'
}]
const obj1 = {
  prop1: 'value1',
  prop2: 'value2'
}
const obj2 = {
  prop2: 'value2',
  prop1: 'value1'
}
const obj3 = {
  prop0: 'value0',
  prop1: 'value1'
}
arrayContainsObject(arr, obj1) // true
arrayContainsObject(arr, obj2) // true, even when props are arranged in different order
arrayContainsObject(arr, obj3) // false


之前的答案,不要使用(因为道具在对象中的顺序需要相同)

const arr = [{
  prop: 'value'
}]
const obj = {
  prop: 'value'
}
arr.some((e) => Object.entries(e).toString() === Object.entries(obj).toString()) // true