找出JavaScript数组是否包含值的最简洁有效的方法是什么?

这是我知道的唯一方法:

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

有没有更好、更简洁的方法来实现这一点?

这与堆栈溢出问题密切相关。在JavaScript数组中查找项目的最佳方法是什么?它解决了使用indexOf查找数组中的对象的问题。


当前回答

原型是这样做的:

/**
 *  Array#indexOf(item[, offset = 0]) -> Number
 *  - item (?): A value that may or may not be in the array.
 *  - offset (Number): The number of initial items to skip before beginning the
 *      search.
 *
 *  Returns the position of the first occurrence of `item` within the array &mdash; or
 *  `-1` if `item` doesn't exist in the array.
**/
function indexOf(item, i) {
  i || (i = 0);
  var length = this.length;
  if (i < 0) i = length + i;
  for (; i < length; i++)
    if (this[i] === item) return i;
  return -1;
}

另请参见此处了解它们是如何连接的。

其他回答

如果你使用的是JavaScript 1.6或更高版本(Firefox 1.5或更高),你可以使用Array.indexOf。

Use:

Array.prototype.contains = function(x){
  var retVal = -1;

  // x is a primitive type
  if(["string","number"].indexOf(typeof x)>=0 ){ retVal = this.indexOf(x);}

  // x is a function
  else if(typeof x =="function") for(var ix in this){
    if((this[ix]+"")==(x+"")) retVal = ix;
  }

  //x is an object...
  else {
    var sx=JSON.stringify(x);
    for(var ix in this){
      if(typeof this[ix] =="object" && JSON.stringify(this[ix])==sx) retVal = ix;
    }
  }

  //Return False if -1 else number if numeric otherwise string
  return (retVal === -1)?false : ( isNaN(+retVal) ? retVal : +retVal);
}

我知道这不是最好的方法,但由于没有本机的IComparable方法来在对象之间进行交互,我想这是比较数组中两个实体所能做到的。此外,扩展Array对象可能不是明智的做法,但有时也可以(如果您意识到这一点和权衡)。

使用lodash的一些功能。

它简洁、准确,并且具有强大的跨平台支持。

接受的答案甚至不符合要求。

要求:推荐最简洁有效的方法来确定JavaScript数组是否包含对象。

接受答案:

$.inArray({'b': 2}, [{'a': 1}, {'b': 2}])
> -1

我的建议:

_.some([{'a': 1}, {'b': 2}], {'b': 2})
> true

笔记:

$.inArray可以很好地确定标量数组中是否存在标量值。。。

$.inArray(2, [1,2])
> 1

…但这个问题显然需要一种有效的方法来确定数组中是否包含对象。

为了处理标量和对象,可以执行以下操作:

(_.isObject(item)) ? _.some(ary, item) : (_.indexOf(ary, item) > -1)

我查看了提交的答案,发现只有通过引用搜索对象时,这些答案才适用。具有参考对象比较的简单线性搜索。

但是,假设您没有对象的引用,如何在数组中找到正确的对象?您必须对每个对象进行线性和深度比较。想象一下,如果列表太大,并且其中的对象非常大,包含大量文本。随着阵列中元素的数量和大小,性能急剧下降。

您可以将对象字符串化并将其放入本机哈希表中,但这样您就有了记住这些键的数据冗余,因为JavaScript将它们保存为“for i in obj”,您只需要检查对象是否存在,也就是说,您拥有该键。

我考虑了一段时间来构建一个JSON模式验证器,我为本地哈希表设计了一个简单的包装器,类似于唯一的哈希表实现,但一些优化异常我留给本地哈希表处理。它只需要性能基准。。。所有详细信息和代码都可以在我的博客上找到:http://stamat.wordpress.com/javascript-quickly-find-very-large-objects-in-a-large-array/我将很快发布基准结果。

完整的解决方案如下所示:

var a = {'a':1,
 'b':{'c':[1,2,[3,45],4,5],
 'd':{'q':1, 'b':{'q':1, 'b':8},'c':4},
 'u':'lol'},
 'e':2};

 var b = {'a':1, 
 'b':{'c':[2,3,[1]],
 'd':{'q':3,'b':{'b':3}}},
 'e':2};

 var c = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";

 var hc = new HashCache([{a:3, b:2, c:5}, {a:15, b:2, c:'foo'}]); //init

 hc.put({a:1, b:1});
 hc.put({b:1, a:1});
 hc.put(true);
 hc.put('true');
 hc.put(a);
 hc.put(c);
 hc.put(d);
 console.log(hc.exists('true'));
 console.log(hc.exists(a));
 console.log(hc.exists(c));
 console.log(hc.exists({b:1, a:1}));
 hc.remove(a);
 console.log(hc.exists(c));

如果您只是试图检查某个值是否包含在集合中,则使用Set更合适,因为数组可以具有重复的值,而Set不能。此外,用set.has替换array.includes可以将性能从O(n2)提高到O(n)。当您必须查找同一集合的多个值时,这将非常有用。因此,如果您只是要查找一个值,那么使用set.has没有任何好处,您可以只使用array.includes。

创建了一个jsbench演示,您可以运行它来检查性能。

测试执行截图: