如何确定对象是否在数组中

我需要确定一个对象是否已经存在于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数组中

例如:

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

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

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

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

没有jquery

500430 次浏览

可以这样说:

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;
}

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

你可以只使用相等操作符:==。默认情况下,对象是通过引用进行检查的,因此甚至不需要使用===操作符。

试试这个,只要确保你在car1的位置使用了正确的变量引用:

var i, car, l = cars.length;


for (i = 0; i < l; i++)
{
if ((car = cars[i]) == car1)
{
break;
}
else car = null;
}

编辑添加:

前面提到了一个数组扩展,下面是它的代码:

Array.prototype.contains = Array.prototype.contains || function(obj)
{
var i, l = this.length;
for (i = 0; i < l; i++)
{
if (this[i] == obj) return true;
}
return false;
};

注意,我正在缓存长度值,因为数组的length属性实际上是一个访问器,它比内部变量稍微慢一些。

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

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

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

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

我使用underscore javascript库来调整这个问题。

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

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

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

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

看看这个:MDN indexOf数组

只是做的事:

carBrands.indexOf(car1);

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

http://jsfiddle.net/Fraximus/r154cd9o

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

我知道这是一个老帖子,但我想提供一个JQuery插件版本和我的代码。

// Find the first occurrence of object in list, Similar to $.grep, but stops searching
function findFirst(a,b){
var i; for (i = 0; i < a.length; ++i) { if (b(a[i], i)) return a[i]; } return undefined;
}

用法:

var product = $.findFirst(arrProducts, function(p) { return p.id == 10 });

我将在数组上使用属性/值的泛型迭代器。不需要jQuery。

arr = [{prop1: 'val1', prop2: 'val2'}, {prop1: 'val3', prop2: 'val4'}];


objectPropInArray(arr, 'prop1', 'val3'); // <-- returns true


function objectPropInArray(list, prop, val) {
if (list.length > 0 ) {
for (i in list) {
if (list[i][prop] === val) {
return true;
}
}
}
return false;
}

这个函数检查一个唯一的字段。 参数1:包含选定数据的数组 参数2:要检查的键 参数3:必须“验证”的值

function objectUnique( array, field, value )
{
var unique = true;
array.forEach(function ( entry )
{
if ( entry[field] == value )
{
unique = false;
}
});


return unique;
}

最近被FP bug咬了一口,阅读了许多关于函数式范式如何与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页面填充部分

或者,我想对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)
}

尝试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


编辑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

如果可能的话,使用es6

carBrands.filter(carBrand => carBrand.name === carX.name).length > 0

如果这是真的,那就有相似之处

您可以将这两个JSON对象转换为字符串,并简单地检查较大的JSON是否包含较小的JSON。

console.log(JSON.stringify(carBrands).includes(JSON.stringify(car1))); // true


console.log(JSON.stringify(carBrands).includes(JSON.stringify(car5))); // false

你可以使用Array.find ()

在你的例子中是这样的

carBrands.find(function(car){
let result  = car.name === 'ford'
if (result == null){
return false;
} else {
return true
}
});

如果car不为空,它将返回包含字符串'ford'的javaScript对象

试试这个, 您可以使用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>

你也可以使用findIndex

var carBrands = [];


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


carBrands.push(car1);


if (carBrands.findIndex(f => f.name === car1.name) === -1) {
console.log('not contain')
} else {
console.log('contain')
}




if (carBrands.findIndex(f => f.name === car2.name) === -1) {
console.log('not contain')
} else {
console.log('contain')
}

这里许多答案的问题是,它们将在数组中找到一个对象,该对象的平等的指向另一个对象。它们将只搜索数组中有指针指向它的现有的对象。

快速修复使用lodash查看ANY 平等的对象是否在数组中:

import _ from 'lodash';
_.find(carBrands, car1); //returns object if true, undefined if false

工作活塞使用此方法:https://plnkr.co/edit/y2YX9o7zkQa2r7lJ