找出JavaScript数组是否包含值的最简洁有效的方法是什么?
这是我知道的唯一方法:
function contains(a, obj) {
for (var i = 0; i < a.length; i++) {
if (a[i] === obj) {
return true;
}
}
return false;
}
有没有更好、更简洁的方法来实现这一点?
这与堆栈溢出问题密切相关。在JavaScript数组中查找项目的最佳方法是什么?它解决了使用indexOf查找数组中的对象的问题。
表演
今天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#includes,这正是做到这一点的,除IE外,所有人都广泛支持它:
console.log(['joe','jane','mary']includes('jane]))//真的
您也可以使用Array#indexOf,它不那么直接,但对于过时的浏览器不需要polyfill。
console.log(['joe','jane','smary'].indexOf('jane')>=0)//真的
许多框架也提供类似的方法:
jQuery:$.inArray(value,array,[fromIndex])Undercore.js:_.inclus(数组,值)(别名为_.include和_.includes)DojoToolkit:Dojo.indexOf(array,value,[fromIndex,findLast])原型:array.indexOf(value)MooTools:array.indexOf(value)MochiKit:findValue(数组,值)MS Ajax:array.indexOf(值)Ext:Ext.Array.contains(数组,值)Lodash:_.includes(array,value,[from])(是_.包含4.0.0之前的版本)Ramda:R.includes(值,数组)
请注意,一些框架将其作为函数实现,而另一些框架将该函数添加到数组原型中。
复杂性O(n/2)
您可以使用任何库函数,但我使用的是核心JavaScript。如果返回true,我们首先搜索中间的元素,否则我们同时从左到中和从右到中搜索数组中的元素。因此,它将具有O(n/2)复杂性。并且它将返回true或false,指示它是否存在
let isExist = (arr, element)=> {
let index = -1;
if ((arr.length % 2 != 0) && arr[(arr.length-1)/2]===element) {
index = 1;
return true;
}
for(let i=0; i<Math.ceil(arr.length-1/2); i++){
if (arr[i]===element || (arr[arr.length-i]===element)) {
index = i;
break;
}
}
return (index<0)? false : true;
}
let array = ['apple', 'ball', 'cat', 'dog', 'egg']
console.log(isExist(array, 'yellow'));
//Result false because yellow doesn't exist in array
console.log(isExist(array, 'cat'));
//Result true because yellow exist in array