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


当前回答

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

其他回答

我知道这是一个老帖子,但我想提供一个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;  
}

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

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

console.log(JSON.stringify(carBrands).includes(JSON.stringify(car5))); // 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值,因为Array的length属性实际上是一个访问器,这比内部变量稍微慢一些。

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

看看这个:MDN indexOf Arrays

只是做的事:

carBrands.indexOf(car1);

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

http://jsfiddle.net/Fraximus/r154cd9o

Edit: Note that in the question, the requirements are to check for the same object referenced in the array, and NOT a new object. Even if the new object is identical in content to the object in the array, it is still a different object. As mentioned in the comments, objects are passed by reference in JS and the same object can exist multiple times in multiple structures. If you want to create a new object and check if the array contains objects identical to your new one, this answer won't work (Julien's fiddle below), if you want to check for that same object's existence in the array, then this answer will work. Check out the fiddles here and in the comments.