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

这是我知道的唯一方法:

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

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

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


当前回答

想一想,如果您多次调用此调用,那么使用关联数组Map使用哈希函数进行查找会更有效。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map

其他回答

如果您正在重复检查数组中是否存在对象,您可能应该查看

通过在数组中执行插入排序(将新对象放在正确的位置),始终保持数组排序将更新对象设置为删除+排序插入操作和在contains(a,obj)中使用二进制搜索查找。

将唯一项目添加到其他列表

searchResults: [
                {
                    name: 'Hello',
                    artist: 'Selana',
                    album: 'Riga',
                    id: 1,
                },
                {
                    name: 'Hello;s',
                    artist: 'Selana G',
                    album: 'Riga1',
                    id: 2,
                },
                {
                    name: 'Hello2',
                    artist: 'Selana',
                    album: 'Riga11',
                    id: 3,
                }
            ],
            playlistTracks: [
              {
                name: 'Hello',
                artist: 'Mamunuus',
                album: 'Riga',
                id: 4,
              },
              {
                name: 'Hello;s',
                artist: 'Mamunuus G',
                album: 'Riga1',
                id: 2,
              },
              {
                name: 'Hello2',
                artist: 'Mamunuus New',
                album: 'Riga11',
                id: 3,
              }
            ],
            playlistName: "New PlayListTrack",
        };
    }

    // Adding an unique track in the playList
    addTrack = track => {
      if(playlistTracks.find(savedTrack => savedTrack.id === track.id)) {
        return;
      }
      playlistTracks.push(track);

      this.setState({
        playlistTracks
      })
    };

这里是Array.indexOf的JavaScript 1.6兼容实现:

if (!Array.indexOf) {
    Array.indexOf = [].indexOf ?
        function(arr, obj, from) {
            return arr.indexOf(obj, from);
        } :
        function(arr, obj, from) { // (for IE6)
            var l = arr.length,
                i = from ? parseInt((1 * from) + (from < 0 ? l : 0), 10) : 0;
            i = i < 0 ? 0 : i;
            for (; i < l; i++) {
                if (i in arr && arr[i] === obj) {
                    return i;
                }
            }
            return -1;
        };
}

表演

今天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个元素

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

上面的答案假设是基元类型,但如果您想知道数组是否包含具有某种特征的对象,array.protocol.some()是一个很好的解决方案:

const items = [ {a: '1'}, {a: '2'}, {a: '3'} ]

items.some(item => item.a === '3')  // returns true
items.some(item => item.a === '4')  // returns false

它的好处是,一旦找到元素,迭代就被中止,从而避免了不必要的迭代周期。

此外,它很适合if语句,因为它返回布尔值:

if (items.some(item => item.a === '3')) {
  // do something
}

*正如jamess在评论中指出的那样,在2018年9月回答这个问题时,Array.protocol.some()是完全支持的:caniuse.com支持表