在 JavaScript 中如何检查数组是否包含值?
找出 JavaScript 数组是否包含值的最简洁、最有效的方法是什么?
这是我知道的唯一方法:
function contains(a, obj) {
for (var i = 0; i < a.length; i++) {
if (a[i] === obj) {
return true;
}
}
return false;
}
是否有更好、更简洁的方法来完成此任务?
这与 Stack Overflow 问题密切相关在 JavaScript 数组中查找项目的最佳方法? 它解决了使用 indexOf
在数组中查找对象的问题。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(30)
现代浏览器有
Array#includes
,它完全做到了这一点,并且受到除 IE 之外的所有人的广泛支持:您还可以使用
Array#indexOf< /code>
,不太直接,但不需要针对过时的浏览器进行填充。
许多框架也提供类似的方法:
$.inArray(value, array, [fromIndex])
_.contains(数组,值)
< /a> (也别名为_.include
和_.includes
)dojo.indexOf(array, value, [fromIndex, findLast])
array.indexOf(value)
array.indexOf(value)
findValue(array, value)
array.indexOf(value)
Ext.Array.contains(array, value)
_.includes(array, value, [from])
(4.0.0 之前的_.contains
)R.includes(value, array)
请注意,某些框架将其实现为函数,而其他框架则添加了函数到数组原型。
Modern browsers have
Array#includes
, which does exactly that and is widely supported by everyone except IE:You can also use
Array#indexOf
, which is less direct, but doesn't require polyfills for outdated browsers.Many frameworks also offer similar methods:
$.inArray(value, array, [fromIndex])
_.contains(array, value)
(also aliased as_.include
and_.includes
)dojo.indexOf(array, value, [fromIndex, findLast])
array.indexOf(value)
array.indexOf(value)
findValue(array, value)
array.indexOf(value)
Ext.Array.contains(array, value)
_.includes(array, value, [from])
(is_.contains
prior 4.0.0)R.includes(value, array)
Notice that some frameworks implement this as a function, while others add the function to the array prototype.
2019 年更新:这个答案来自 2008 年(11 岁了!),与现代 JS 的使用无关。 承诺的性能改进是基于当时浏览器中完成的基准测试。 它可能与现代 JS 执行上下文无关。 如果您需要简单的解决方案,请寻找其他答案。 如果您需要最佳性能,请在相关执行环境中对自己进行基准测试。
正如其他人所说,通过数组进行迭代可能是最好的方法,但它 已被证明,递减的
while
循环是JavaScript 中迭代的最快方法。 所以你可能想重写你的代码如下:当然,你也可以扩展 Array 原型:
现在你可以简单地使用以下内容:
Update from 2019: This answer is from 2008 (11 years old!) and is not relevant for modern JS usage. The promised performance improvement was based on a benchmark done in browsers of that time. It might not be relevant to modern JS execution contexts. If you need an easy solution, look for other answers. If you need the best performance, benchmark for yourself in the relevant execution environments.
As others have said, the iteration through the array is probably the best way, but it has been proven that a decreasing
while
loop is the fastest way to iterate in JavaScript. So you may want to rewrite your code as follows:Of course, you may as well extend Array prototype:
And now you can simply use the following:
最上面的答案假设原始类型,但如果您想查明数组是否包含具有某些特征的对象,Array.prototype.some() 是一个优雅的解决方案:
它的好处是一旦找到元素,迭代就会中止,因此避免了不必要的迭代周期。
此外,它非常适合
if
语句,因为它返回一个布尔值:* 正如 jamess 在评论中指出的那样,在 2018 年 9 月发表此答案时,
Array.prototype.some( )
完全支持:caniuse.com 支持表The top answers assume primitive types but if you want to find out if an array contains an object with some trait, Array.prototype.some() is an elegant solution:
The nice thing about it is that the iteration is aborted once the element is found so unnecessary iteration cycles are spared.
Also, it fits nicely in an
if
statement since it returns a boolean:* As jamess pointed out in the comment, at the time of this answer, September 2018,
Array.prototype.some()
is fully supported: caniuse.com support tableindexOf
也许,但它是“ECMA-262 标准的 JavaScript 扩展;因此,它可能不存在于该标准的其他实现中。”示例:
AFAICS Microsoft 不 对此提供了某种替代方案,但如果您愿意,您可以向 Internet Explorer(以及其他不支持
indexOf
的浏览器)中的数组添加类似的功能,作为快速 Google 搜索显示(例如,这个)。indexOf
maybe, but it's a "JavaScript extension to the ECMA-262 standard; as such it may not be present in other implementations of the standard."Example:
AFAICS Microsoft does not offer some kind of alternative to this, but you can add similar functionality to arrays in Internet Explorer (and other browsers that don't support
indexOf
) if you want to, as a quick Google search reveals (for example, this one).ECMAScript 7 引入了
Array.prototype.includes
。它可以这样使用:
它还接受可选的第二个参数
fromIndex
:与
indexOf
不同,它使用 严格相等比较,包含
使用SameValueZero 相等算法。 这意味着您可以检测数组是否包含NaN
:与
indexOf
不同的是,includes
不会跳过缺失的索引:它可以是 polyfilled 使其适用于所有浏览器。
ECMAScript 7 introduces
Array.prototype.includes
.It can be used like this:
It also accepts an optional second argument
fromIndex
:Unlike
indexOf
, which uses Strict Equality Comparison,includes
compares using SameValueZero equality algorithm. That means that you can detect if an array includes aNaN
:Also unlike
indexOf
,includes
does not skip missing indices:It can be polyfilled to make it work on all browsers.
假设您已经像这样定义了一个数组:
下面是检查其中是否有
3
的三种方法。 它们都返回true
或false
。原生数组方法(自 ES2016 起)(兼容性表)
作为自定义数组方法(ES2016 之前)
简单功能
Let's say you've defined an array like so:
Below are three ways of checking whether there is a
3
in there. All of them return eithertrue
orfalse
.Native Array method (since ES2016) (compatibility table)
As custom Array method (pre ES2016)
Simple function
这是 JavaScript 1.6 兼容
Array.indexOf 实现:
Here's a JavaScript 1.6 compatible implementation of
Array.indexOf
:使用:
Use:
扩展 JavaScript
Array
对象是一个非常糟糕的主意,因为您将新属性(您的自定义方法)引入到for-in
循环中,这可能会破坏现有脚本。 几年前,Prototype 库的作者必须重新设计他们的库实现,以删除仅这种事。如果您不需要担心与页面上运行的其他 JavaScript 的兼容性,请使用它,否则,我会推荐更尴尬但更安全的独立函数解决方案。
Extending the JavaScript
Array
object is a really bad idea because you introduce new properties (your custom methods) intofor-in
loops which can break existing scripts. A few years ago the authors of the Prototype library had to re-engineer their library implementation to remove just this kind of thing.If you don't need to worry about compatibility with other JavaScript running on your page, go for it, otherwise, I'd recommend the more awkward, but safer free-standing function solution.
今天的性能
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包含<的所有浏览器上是最
for
(C,D) 和indexOf
(G,H) 的解决方案在所有浏览器上都相当快小数组和大数组,因此它们可能是有效解决方案的最佳选择,for
(C,D,E) 的解决方案给出了类似的结果(~630 操作/秒 - 但E 在 safari 和 firefox 上比 C 和 D 慢 10-20%)结果
详细信息
我执行 2 个测试用例:对于具有 10 个元素的数组,以及具有 100 万个元素的数组。 在这两种情况下,我们都将搜索到的元素放在数组中间。
小型数组 - 10 个元素
您可以此处
Array big - 1.000.000 个元素
您可以在计算机中执行测试这里
Performance
Today 2020.01.07 I perform tests on MacOs HighSierra 10.13.6 on Chrome v78.0.0, Safari v13.0.4 and Firefox v71.0.0 for 15 chosen solutions. Conclusions
JSON
,Set
and surprisinglyfind
(K,N,O) are slowest on all browsersincludes
(F) is fast only on chromefor
(C,D) andindexOf
(G,H) are quite-fast on all browsers on small and big arrays so probably they are best choice for efficient solutionfor
(C,D,E) gives similar results (~630 ops/sec - but the E on safari and firefox was 10-20% slower than C and D)Results
Details
I perform 2 tests cases: for array with 10 elements, and array with 1 milion elements. In both cases we put searched element in the array middle.
Array small - 10 elements
You can perform tests in your machine HERE
Array big - 1.000.000 elements
You can perform tests in your machine HERE
单线:
One-liner:
跳出框框思考一下,如果您多次进行此调用,那么使用
关联数组Map 来使用散列函数进行查找会更有效。https://developer.mozilla.org/en-US /docs/Web/JavaScript/Reference/Global_Objects/Map
Thinking out of the box for a second, if you are making this call many many times, it is vastly more efficient to use
an associative arraya Map to do lookups using a hash function.https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
我使用以下内容:
I use the following:
Array.prototype.some() 已添加到 ECMA第五版-262标准
Array.prototype.some() was added to the ECMA-262 standard in the 5th edition
有几种方法可以轻松实现(
includes
、some
、find
、findIndex
)有关包含的更多信息,一些,查找,findIndex
There are a couple of methods which makes it easy to achieve (
includes
,some
,find
,findIndex
)More about includes, some, find, findIndex
如果您使用的是 JavaScript 1.6 或更高版本(Firefox 1.5 或更高版本),您可以使用 Array.indexOf。 否则,我认为您最终会得到与原始代码类似的结果。
If you are using JavaScript 1.6 or later (Firefox 1.5 or later) you can use Array.indexOf. Otherwise, I think you are going to end up with something similar to your original code.
希望更快的双向
indexOf
/lastIndexOf
替代方案2015
而新方法
includes
非常好,目前支持基本为零。很长一段时间以来,我一直在思考一种方法来取代缓慢的
indexOf
/lastIndexOf
函数。通过查看最热门的答案,已经找到了一种高性能的方法。 从这些中,我选择了 @Damir Zekic 发布的
contains
函数,它应该是最快的函数。 但它也指出,基准来自 2008 年,因此已经过时。我也更喜欢
while
而不是for
,但由于没有特定原因,我最终用 for 循环编写了该函数。 也可以使用while --
来完成。我很好奇如果我在执行迭代时检查数组的两侧,迭代是否会慢得多。 显然不是,所以这个函数比投票最多的函数快大约两倍。 显然它也比原生的更快。 这是在现实环境中,您永远不知道要搜索的值是在数组的开头还是结尾。
当您知道您刚刚推送了一个带有值的数组时,使用 lastIndexOf 可能仍然是最好的解决方案,但如果您必须遍历大数组并且结果可能无处不在,那么这可能是一个使事情变得更快的可靠解决方案。
双向
indexOf
/lastIndexOf
性能测试
https ://jsbench.me/7el1b8dj80
作为测试,我创建了一个包含 100k 条目的数组。
三个查询:开头、中间和第三个查询 在数组的末尾。
我希望您也觉得这很有趣并测试其性能。
注意:正如您所看到的,我稍微修改了
contains
函数以反映indexOf
&lastIndexOf
输出(所以基本上true
带有index
和false
带有-1
) 。 这不应该伤害它。数组原型变体
该函数还可以轻松修改以返回 true 或 false 甚至对象、字符串或其他任何内容。
这是
while
变体:这怎么可能?
我认为获取数组中的反射索引的简单计算非常简单,比实际循环迭代快两倍。
这是一个复杂的示例,每次迭代执行三次检查,但这只能通过较长的计算来实现,这会导致代码速度减慢。
https://web.archive.org/web/ 20151019160219/http://jsperf.com/bidirectionindexof/2
A hopefully faster bidirectional
indexOf
/lastIndexOf
alternative2015
While the new method
includes
is very nice, the support is basically zero for now.It's a long time that I was thinking of a way to replace the slow
indexOf
/lastIndexOf
functions.A performant way has already been found, looking at the top answers. From those I chose the
contains
function posted by @Damir Zekic which should be the fastest one. But it also states that the benchmarks are from 2008 and so are outdated.I also prefer
while
overfor
, but for not a specific reason I ended writing the function with a for loop. It could be also done with awhile --
.I was curious if the iteration was much slower if I check both sides of the array while doing it. Apparently no, and so this function is around two times faster than the top voted ones. Obviously it's also faster than the native one. This is in a real world environment, where you never know if the value you are searching is at the beginning or at the end of the array.
When you know you just pushed an array with a value, using lastIndexOf remains probably the best solution, but if you have to travel through big arrays and the result could be everywhere, this could be a solid solution to make things faster.
Bidirectional
indexOf
/lastIndexOf
Performance test
https://jsbench.me/7el1b8dj80
As a test I created an array with 100k entries.
Three queries: at the beginning, in the middle & at the end of the array.
I hope you also find this interesting and test the performance.
Note: As you can see I slightly modified the
contains
function to reflect theindexOf
&lastIndexOf
output (so basicallytrue
with theindex
andfalse
with-1
). That shouldn't harm it.The array prototype variant
The function can also be easily modified to return true or false or even the object, string or whatever it is.
And here is the
while
variant:How is this possible?
I think that the simple calculation to get the reflected index in an array is so simple that it's two times faster than doing an actual loop iteration.
Here is a complex example doing three checks per iteration, but this is only possible with a longer calculation which causes the slowdown of the code.
https://web.archive.org/web/20151019160219/http://jsperf.com/bidirectionalindexof/2
如果找到则返回数组索引,如果未找到则返回-1
Returns array index if found, or -1 if not found
如果您重复检查数组中是否存在对象,您可能应该
contains(a, obj)
中查找。If you are checking repeatedly for existence of an object in an array you should maybe look into
contains(a, obj)
.我们使用此代码片段(适用于对象、数组、字符串):
用法:
We use this snippet (works with objects, arrays, strings):
Usage:
适用于所有现代浏览器的解决方案:
用法:
IE6+ 解决方案:
用法:
为什么要使用
JSON.stringify
?Array.indexOf
和Array.includes
(以及此处的大多数答案)仅通过引用进行比较,而不是通过值进行比较。附赠
未优化的 ES6 单行代码:
注意:
如果键的顺序相同,则按值比较对象会更好,因此为了安全起见,您可以首先使用如下所示的包对键进行排序: https://www.npmjs.com/package/sort-keys
通过性能优化更新了
contains
函数。 感谢 itinance 指出这一点。Solution that works in all modern browsers:
Usage:
IE6+ solution:
Usage:
Why to use
JSON.stringify
?Array.indexOf
andArray.includes
(as well as most of the answers here) only compare by reference and not by value.Bonus
Non-optimized ES6 one-liner:
Note:
Comparing objects by value will work better if the keys are in the same order, so to be safe you might sort the keys first with a package like this one: https://www.npmjs.com/package/sort-keys
Updated the
contains
function with a perf optimization. Thanks itinance for pointing it out.使用 lodash 的 some 函数。
它简洁、准确并且具有强大的跨平台支持。
接受的答案甚至不符合要求。
要求:推荐最简洁有效的方法来查明 JavaScript 数组是否包含对象。
接受的答案:
我的建议:
注意:
$.inArray 可以很好地确定标量数组中是否存在标量值
...。 ..但问题显然需要一种有效的方法来确定对象是否包含在数组中。
为了处理标量和对象,您可以这样做:
Use lodash's some function.
It's concise, accurate and has great cross platform support.
The accepted answer does not even meet the requirements.
Requirements: Recommend most concise and efficient way to find out if a JavaScript array contains an object.
Accepted Answer:
My recommendation:
Notes:
$.inArray works fine for determining whether a scalar value exists in an array of scalars...
... but the question clearly asks for an efficient way to determine if an object is contained in an array.
In order to handle both scalars and objects, you could do this:
满足此要求的简单解决方案是使用
find()
如果您有如下所示的对象数组,
那么您可以检查具有您的值的对象是否已经存在:
如果数据为 null 则不存在admin,否则它将返回现有对象,例如:
然后您可以在数组中找到该对象的索引并使用代码替换该对象:
您将获得如下值:
Simple solution for this requirement is using
find()
If you're having array of objects like below,
Then you can check whether the object with your value is already present or not:
if data is null then no admin, else it will return the existing object like:
Then you can find the index of that object in the array and replace the object using the code:
you will get value like:
ECMAScript 6 对 find 有一个优雅的建议。
这是关于该问题的 MDN 文档 。
查找功能的工作原理如下。
您可以通过 定义函数。
ECMAScript 6 has an elegant proposal on find.
Here is the MDN documentation on that.
The find functionality works like this.
You can use this in ECMAScript 5 and below by defining the function.
虽然 array.indexOf(x)!=-1 是执行此操作的最简洁方法(并且非 Internet Explorer 浏览器已支持十多年......),但它并不是 O (1),而是 O(N),这很糟糕。 如果您的数组不会更改,您可以将数组转换为哈希表,然后执行
table[x]!==undefined
或===undefined
:演示:
(不幸的是,虽然您可以创建 Array.prototype.contains 来“冻结”数组并在 this._cache 中分两行存储哈希表,但如果您选择稍后编辑数组,则这会产生错误的结果。你可以保持这种状态,这与 Python 不同。)
While
array.indexOf(x)!=-1
is the most concise way to do this (and has been supported by non-Internet Explorer browsers for over decade...), it is not O(1), but rather O(N), which is terrible. If your array will not be changing, you can convert your array to a hashtable, then dotable[x]!==undefined
or===undefined
:Demo:
(Unfortunately, while you can create an Array.prototype.contains to "freeze" an array and store a hashtable in this._cache in two lines, this would give wrong results if you chose to edit your array later. JavaScript has insufficient hooks to let you keep this state, unlike Python for example.)
可以使用具有方法“has( )”:
One can use Set that has the method "has()":
使用:
Demo
要确切了解
波浪号
~
此时请参考这个问题 当波浪号出现在表达式之前时,它有什么作用?。Use:
Demo
To know exactly what the
tilde
~
do at this point, refer to this question What does a tilde do when it precedes an expression?.好的,您只需优化您的代码即可获得结果!
有很多方法可以做到这一点,这些方法更干净、更好,但我只是想获取您的模式并使用
JSON.stringify
应用于该模式,只需在您的情况下执行如下操作:OK, you can just optimise your code to get the result!
There are many ways to do this which are cleaner and better, but I just wanted to get your pattern and apply to that using
JSON.stringify
, just simply do something like this in your case:令人惊讶的是这个问题仍然没有添加最新的语法,添加我的 2 美分。
假设我们有对象数组 arrObj 并且我们想要在其中搜索 obj 。
Array.prototype.indexOf -> (返回索引或-1)通常用于查找数组中元素的索引。
这也可以用于搜索对象,但仅当您传递对同一对象的引用时才有效。
Array.prototype.包含 -> (返回true或false)
Array.prototype.find -> (接受回调,返回第一个在 CB 中返回 true 的值/对象)。
Array.prototype.findIndex -> (接受回调,返回 CB 中返回 true 的第一个值/对象的索引)。
由于 find 和 findIndex 需要回调,因此我们可以通过创造性地设置 true 条件从数组中获取任何对象(即使我们没有引用)。
Surprised that this question still doesn't have latest syntax added, adding my 2 cents.
Let's say we have array of Objects arrObj and we want to search obj in it.
Array.prototype.indexOf -> (returns index or -1) is generally used for finding index of element in array.
This can also be used for searching object but only works if you are passing reference to same object.
Array.prototype.includes -> (returns true or false)
Array.prototype.find -> (takes callback, returns first value/object that returns true in CB).
Array.prototype.findIndex -> (takes callback, returns index of first value/object that returns true in CB).
Since find and findIndex takes a callback, we can be fetch any object(even if we don't have the reference) from array by creatively setting the true condition.
它有一个参数:一组对象。 数组中的每个对象都有两个整数属性,用 x 和 y 表示。 该函数必须返回数组中满足
numbers.x ==numbers.y
的所有此类对象的计数It has one parameter: an array numbers of objects. Each object in the array has two integer properties denoted by x and y. The function must return a count of all such objects in the array that satisfy
numbers.x == numbers.y