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

这是我知道的唯一方法:

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

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

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


当前回答

Use:

function isInArray(array, search)
{
    return array.indexOf(search) >= 0;
}

// Usage
if(isInArray(my_array, "my_value"))
{
    //...
}

其他回答

原型是这样做的:

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

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

而array.indexOf(x)=-1是实现这一点的最简洁的方法(并且已经被非Internet Explorer浏览器支持了十多年……),它不是O(1),而是O(N),这很可怕。如果您的数组不会改变,您可以将数组转换为哈希表,然后执行表[x]==未定义或==未定义:

Array.prototype.toTable = function() {
    var t = {};
    this.forEach(function(x){t[x]=true});
    return t;
}

演示:

var toRemove = [2,4].toTable();
[1,2,3,4,5].filter(function(x){return toRemove[x]===undefined})

(不幸的是,虽然您可以创建Array.prototype.contains来“冻结”数组并将哈希表存储在this._cache中,但如果您选择稍后编辑数组,则会产生错误的结果。与Python不同,JavaScript没有足够的钩子来保持这种状态。)

表演

今天2020.01.07我在Chrome v78.0.0、Safari v13.0.4和Firefox v71.0.0上对MacOs HighSierra 10.13.6进行了测试,测试了15个选定的解决方案。结论

基于JSON、Set和意外find(K、N、O)的解决方案在所有浏览器上都是最慢的es6包括(F)仅在铬上快速基于for(C,D)和indexOf(G,H)的解决方案在大小阵列上的所有浏览器上都非常快,因此它们可能是高效解决方案的最佳选择循环期间索引减少的解决方案(B)可能较慢,因为CPU缓存的工作方式。当搜索到的元素位于阵列长度的66%时,我也对大阵列进行了测试,基于for(C,D,E)的解决方案给出了类似的结果(约630操作/秒-但safari和firefox上的E比C和D慢10-20%)

后果

细节

我执行了两个测试用例:一个是10个元素的数组,一个是100万元素的数组。在这两种情况下,我们都将搜索到的元素放在数组中间。

let log=(name,f)=>console.log(`${name}:3-${f(arr,'s10')}'s7'-${f,'s7')}6-${f设arr=[1,2,3,4,5,'6','7','8','9','10'];//arr=新数组(1000000).fill(123);arr[500000]=7;函数A(A,val){变量i=-1;var n=a.length;而(i++<n){如果(a[i]===val){返回true;}}return false;}函数B(a,val){var i=a.length;而(i-){如果(a[i]===val){返回true;}}return false;}函数C(a,val){对于(var i=0;i<a.length;i++){如果(a[i]===val)返回true;}return false;}函数D(a,val){var len=a.length;对于(var i=0;i<len;i++){如果(a[i]===val)返回true;}return false;} 函数E(a,val){var n=a.length-1;变量t=n/2;对于(变量i=0;i<=t;i++){如果(a[i]==val ||a[n-i]==val)返回true;}return false;}函数F(a,val){return a.includes(val);}函数G(a,val){return a.indexOf(val)>=0;}函数H(a,val){返回~a.indexOf(val);}函数I(a,val){return a.findIndex(x=>x==val)>=0;}函数J(a,val){返回a.some(x=>x===val);}函数K(a,val){const s=JSON.stringify(val);返回a.some(x=>JSON.stringify(x)==s);}函数L(a,val){回来a.every(x=>x!==val);}函数M(a,val){回来a.查找(x=>x==val);}函数N(a,val){返回a.filter(x=>x===val)。长度>0;}函数O(a,val){返回新集合(a).has(val);}日志('A',A);日志('B',B);日志('C',C);日志('D',D);对数('E',E);日志('F',F);日志('G',G);对数('H',H);日志('I',I);日志('J',J);log('K',K);对数('L',L);日志(M’,M);对数('N',N);日志('O',O);此shippet只显示性能测试中使用的函数,而不执行测试本身!

阵列小-10个元素

您可以在此处的机器中执行测试

数组大-1.000.000个元素

您可以在此处的机器中执行测试

简单的解决方案:ES6功能“包含”方法

let arr = [1, 2, 3, 2, 3, 2, 3, 4];

  arr.includes(2) // true

  arr.includes(93) // false

我使用以下方法:

Array.prototype.contains = function (v) {
    return this.indexOf(v) > -1;
}

var a = [ 'foo', 'bar' ];

a.contains('foo'); // true
a.contains('fox'); // false