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

时间:2011-01-03 18:16:36

标签: javascript

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

11 个答案:

答案 0 :(得分:144)

使用类似的东西:

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

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

答案 1 :(得分:106)

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

检查出来:MDN indexOf Arrays

简单地说:

carBrands.indexOf(car1);

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

http://jsfiddle.net/Fraximus/r154cd9o

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

答案 2 :(得分:17)

您可以使用jQuery's 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"; });

答案 3 :(得分:12)

最近被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似乎不支持它。位于polyfill section of MSDN page

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

答案 4 :(得分:9)

您可以使用等于运算符:==。默认情况下,通过引用检查对象,因此您甚至不需要使用===运算符。

试试这个,只需确保在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;
};

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

答案 5 :(得分:9)

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

答案 6 :(得分:7)

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

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

请参阅underscore.js文档,了解上述示例中使用的下划线功能。

注意:我的解决方案不是纯javascript,因为它使用其他js库。我添加此信息只是为了提供信息。

答案 7 :(得分:7)

我会在数组上使用属性/值的泛型迭代器。不需要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;  
}

答案 8 :(得分:3)

您可以尝试根据属性对数组进行排序,如下所示:

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

大于或小于目标,依此类推,这将允许您快速浏览数组以查找对象是否存在。

答案 9 :(得分:1)

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

答案 10 :(得分:1)

此功能用于检查唯一字段。 Arg 1:包含所选数据的数组 Arg 2:检查的关键 Arg 3:必须“验证”的值

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

    return unique;
}