问题描述:
找出 JavaScript 数组是否包含值的最简洁有效的方法是什么?
这是我知道的唯一方法:
function contains(a, obj) {
for (var i = 0; i < a.length; i++) {
if (a[i] === obj) {
return true;
}
}
return false;
}
有没有更好更简洁的方法来实现这一点?
这与 Stack Overflow 问题 Best way to find an item in a JavaScript Array? 密切相关,该问题解决了使用 indexOf 在数组中查找对象的问题。
解决方案1:
huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感
现代浏览器具有 Array#includes,它完全做到这一点,并且 is widely supported 被除 IE 之外的所有人:
console.log([‘joe’, ‘jane’, ‘mary’].includes(‘jane’)); //真的
您也可以使用 Array#indexOf,它不太直接,但对于过时的浏览器不需要 polyfill。
console.log([‘joe’, ‘jane’, ‘mary’].indexOf(‘jane’) >= 0); //真的
许多框架也提供了类似的方法:
jQuery: $.inArray(value, array, [fromIndex])
Underscore.js:_.contains(array, value)(也别名为 _.include 和 _.includes)
Dojo 工具包:dojo.indexOf(array, value, [fromIndex, findLast])
原型:array.indexOf(value)
MooTools:array.indexOf(值)
MochiKit:findValue(数组,值)
MS Ajax:array.indexOf(value)
分机:Ext.Array.contains(数组,值)
Lodash: _.includes(array, value, [from]) (是 _.contains 之前的 4.0.0)
Ramda:R.includes(值,数组)
请注意,一些框架将其实现为一个函数,而另一些框架则将该函数添加到数组原型中。
MooTools 也有返回布尔值的 Array.contains,这听起来像是这里的真正问题。
原型还具有返回布尔值的 Array.include
如果您使用的是好的浏览器,您可以使用 array.indexOf(object) != -1
另外,不要单独使用 indexOf 作为条件,因为第一个元素将返回 0 并将被评估为 falsy
inArray 是返回元素索引的函数的糟糕名称,如果不存在则返回 -1。我希望返回一个布尔值。
解决方案2:
huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。
2019 年更新:此答案来自 2008 年(11 岁!),与现代 JS 使用无关。承诺的性能改进是基于当时在浏览器中完成的基准测试。它可能与现代 JS 执行上下文无关。如果您需要一个简单的解决方案,请寻找其他答案。如果您需要最佳性能,请在相关执行环境中为自己进行基准测试。
正如其他人所说,通过数组进行迭代可能是最好的方法,但是 has been proven 递减 while 循环是 JavaScript 中迭代的最快方法。所以你可能想重写你的代码如下:
function contains(a, obj) {
var i = a.length;
while (i--) {
if (a[i] === obj) {
return true;
}
}
return false;
}
当然,你也可以扩展 Array 原型:
Array.prototype.contains = function(obj) {
var i = this.length;
while (i--) {
if (this[i] === obj) {
return true;
}
}
return false;
}
现在您可以简单地使用以下内容:
alert([1, 2, 3].contains(2)); // => true
alert([1, 2, 3].contains('2')); // => false
但要小心:stackoverflow.com/questions/237104/javascript-array-containsobj/…
“证明”是一个强有力的词。 JS 引擎不断改进,3 年前测量的执行时间已经过时了。
解决方案3:
huntsbot.com – 高效赚钱,自由工作
indexOf 可能,但它是“ECMA-262 标准的 JavaScript 扩展;因此它可能不存在于该标准的其他实现中。”
例子:
[1, 2, 3].indexOf(1) => 0
["foo", "bar", "baz"].indexOf("bar") => 1
[1, 2, 3].indexOf(4) => -1
AFAICS Microsoft does not offer some kind of alternative,但如果您愿意,可以将类似的功能添加到 Internet Explorer(以及不支持 indexOf 的其他浏览器)中的数组,作为 quick Google search reveals(例如,this one)。
解决方案4:
huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。
最佳答案假定原始类型,但如果您想了解数组是否包含具有某些特征的 object,Array.prototype.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.prototype.some():caniuse.com support table
huntsbot.com – 程序员副业首选,一站式外包任务、远程工作、创意产品分享订阅平台。
我正在使用 Typescript,我的数组包含 Enum 类型的项目。 “包含”对我不起作用,这个解决方案有效。 Typescript 的任何其他解决方案将不胜感激。
解决方案5:
huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!
ECMAScript 7 引入了 Array.prototype.includes。
它可以这样使用:
[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false
它还接受可选的第二个参数 fromIndex:
[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true
与使用 Strict Equality Comparison 的 indexOf 不同,includes 使用 SameValueZero 相等算法进行比较。这意味着您可以检测数组是否包含 NaN:
[1, 2, NaN].includes(NaN); // true
与 indexOf 不同的是,includes 不会跳过缺失的索引:
new Array(5).includes(undefined); // true
可以是 polyfilled 使其适用于所有浏览器。
解决方案6:
保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com
假设您已经定义了一个这样的数组:
const array = [1, 2, 3, 4]
以下是检查其中是否存在 3 的三种方法。它们都返回 true 或 false。
Native Array 方法(自 ES2016 起)(兼容性表)
array.includes(3) // true
作为自定义 Array 方法(ES2016 之前)
// Prefixing the method with '_' to avoid name clashes
Object.defineProperty(Array.prototype, '_includes', { value: function (v) { return this.indexOf(v) !== -1 }})
array._includes(3) // true
简单的功能
const includes = (a, v) => a.indexOf(v) !== -1
includes(array, 3) // true
huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。
"~" 是一个对数字进行取整、取反和减 1 的运算符。 indexOf 如果失败则返回 -1,因此“~”将 -1 变为“0”。使用 ”!!”将数字转换为布尔值 (!!0===false)
解决方案7:
huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。
这是 Array.indexOf 的 JavaScript 1.6 compatible 实现:
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;
};
}
这看起来不错,但有点困惑: * 第 1 行和第 3 行的测试不是等效的吗? * 测试原型,如果有必要,将函数添加到 Array.prototype 中不是更好吗?
它们不是等价的。 [].indexOf 是 Array.prototype.indexOf 的简写。我们偏执的 Javascript 程序员不惜一切代价避免扩展原生原型。
[].indexOf 不是创建一个新数组然后访问 indexOf,而 Array.prototype.indexOf 只是直接访问原型吗?
@alex 是 [].indexOf === Array.prototype.indexOf(在 FireBug 中尝试),但反过来 [].indexOf !== Array.indexOf。
解决方案8:
一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会
利用:
function isInArray(array, search)
{
return array.indexOf(search) >= 0;
}
// Usage
if(isInArray(my_array, "my_value"))
{
//...
}
x ? true : false 通常是多余的。是这里。
@minitech 为什么说它是多余的?
array.indexOf(search) >= 0 已经是一个布尔值。只需 return array.indexOf(search) >= 0。
@minitech 很好,谢谢!其实我不知道这样的建筑可以退货。直到一些新的东西。
解决方案9:
打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!
扩展 JavaScript Array 对象是一个非常糟糕的主意,因为您将新属性(您的自定义方法)引入到 for-in 循环中,这可能会破坏现有脚本。几年前,Prototype 库的作者不得不重新设计他们的库实现以删除这种东西。
如果您不需要担心与页面上运行的其他 JavaScript 的兼容性,那就去吧,否则,我会推荐更笨拙但更安全的独立函数解决方案。
我不同意。正是出于这个原因,for-in 循环不应该用于数组。使用流行的 js 库之一时,使用 for-in 循环会中断
解决方案10:
huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!
表现
今天 2020.01.07 我在 Chrome v78.0.0、Safari v13.0.4 和 Firefox v71.0.0 上对 MacOs HighSierra 10.13.6 进行了 15 种选定解决方案的测试。结论
基于 JSON、Set 和意外发现 (K,N,O) 的解决方案在所有浏览器上最慢
es6 包含 (F) 仅在 chrome 上速度很快
基于 for (C,D) 和 indexOf (G,H) 的解决方案在大小数组上的所有浏览器上都非常快,因此它们可能是有效解决方案的最佳选择
循环期间索引减少的解决方案,(B)较慢可能是因为 CPU 缓存的方式起作用。
当搜索的元素位于数组长度的 66% 位置时,我还对大数组进行了测试,基于 for (C,D,E) 的解决方案给出了类似的结果(~630 ops/sec - 但 safari 和 firefox 上的 E 为 10 -20% 比 C 和 D 慢)
结果
https://i.stack.imgur.com/YPIG1.png
细节
我执行 2 个测试用例:对于具有 10 个元素的数组和具有 100 万个元素的数组。在这两种情况下,我们都将搜索到的元素放在数组中间。
让 log = (name,f) => console.log(${name}: 3-${f(arr,'s10')} 's7'-${f(arr,'s7')} 6- ${f(arr,6)} 's3'-${f(arr,'s3')}
) 让 arr = [1,2,3,4,5,‘s6’,‘s7’,'s8 ',‘s9’,‘s10’]; //arr = new Array(1000000).fill(123); arr[500000]=7;函数 A(a, val) { var i = -1; var n = a.length; while (i++=0; } 函数 H(a,val) { return !!~a.indexOf(val); } 函数 I(a, val) { return a.findIndex(x=> xval)>=0; } 函数 J(a,val) { return a.some(x=> x=val); } 函数 K(a, val) { const s = JSON.stringify(val);返回 a.some(x => JSON.stringify(x) === s); } 函数 L(a,val) { return !a.every(x=> x!val); } 函数 M(a, val) { return !!a.find(x=> xval); } function N(a,val) { return a.filter(x=>x===val).length > 0; } 函数 O(a, val) { return new Set(a).has(val); } 日志(‘A’,A);日志(‘B’,B);日志(‘C’,C);日志(‘D’,D);日志(‘E’,E);日志(‘F’,F);日志(‘G’,G);日志(‘H’,H);日志(‘我’,我);日志(‘J’,J);日志(‘K’,K);日志(‘L’,L);日志(‘M’,M);日志(‘N’,N);日志(‘O’,O);此 Shippet 仅提供性能测试中使用的功能 - 它本身不执行测试!
小数组 - 10 个元素
您可以在您的机器上执行测试 HERE
https://i.stack.imgur.com/gDDCp.png
大数组 - 1.000.000 个元素
您可以在您的机器上执行测试 HERE
https://i.stack.imgur.com/cTL3s.png
解决方案11:
一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会
单线:
function contains(arr, x) {
return arr.filter(function(elem) { return elem == x }).length > 0;
}
array.filter(e=>e==x).length > 0 等价于 array.some(e=>e==x) 但 some 更有效
原文链接:https://www.huntsbot.com/qa/1jdO/how-do-i-check-if-an-array-includes-a-value-in-javascript?lang=zh_CN
huntsbot.com – 程序员副业首选,一站式外包任务、远程工作、创意产品分享订阅平台。