What is the most concise and efficient way to find out if a JavaScript array contains an object?
找出一个JavaScript数组是否包含对象的最简洁和有效的方法是什么?
This is the only way I know to do it:
这是我知道的唯一方法:
function contains(a, obj) {
for (var i = 0; i < a.length; i++) {
if (a[i] === obj) {
return true;
}
}
return false;
}
Is there a better and more concise way to accomplish this?
有没有更好、更简洁的方法来实现这个目标?
This is very closely related to Stack Overflow question Best way to find an item in a JavaScript Array? which addresses finding objects in an array using indexOf
.
这与堆栈溢出问题密切相关,如何在JavaScript数组中找到项?使用indexOf查找数组中的对象。
40 个解决方案
#1
3609
Current browsers have Array#includes
, which does exactly that, is widely supported, and has a polyfill for older browsers.
当前的浏览器有数组#include,它确实做到了这一点,得到了广泛的支持,并且有一个用于旧浏览器的polyfill。
You can also use Array#indexOf
, which is less direct, but doesn't require Polyfills for out of date browsers.
您还可以使用数组#indexOf,它不太直接,但不需要为过期浏览器填充。
jQuery offers $.inArray
, which is functionally equivalent to Array#indexOf
.
jQuery提供美元。inArray,在功能上等同于数组#indexOf。
underscore.js, a JavaScript utility library, offers _.contains(list, value)
, alias _.include(list, value)
, both of which use indexOf internally if passed a JavaScript array.
下划线。JavaScript实用程序库js提供_。包含(列表,价值),别名_。include(list, value),如果传递一个JavaScript数组,它们都在内部使用indexOf。
Some other frameworks offer similar methods:
其他一些框架提供了类似的方法:
- Dojo Toolkit:
dojo.indexOf(array, value, [fromIndex, findLast])
- Dojo Toolkit:Dojo。indexOf(数组、价值[fromIndex findLast])
- Prototype:
array.indexOf(value)
- 原型:array.indexOf(值)
- MooTools:
array.indexOf(value)
- MooTools:array.indexOf(值)
- MochiKit:
findValue(array, value)
- MochiKit:findValue(数组,值)
- MS Ajax:
array.indexOf(value)
- Ajax女士:array.indexOf(值)
- Ext:
Ext.Array.contains(array, value)
- Ext:Ext.Array。包含(数组,价值)
- Lodash:
_.includes(array, value, [from])
(is_.contains
prior 4.0.0) - Lodash:_。包含(数组,值,[from]) (is _。包含4.0.0之前)
- ECMAScript 2016:
array.includes(value)
- ECMAScript 2016:array.includes(值)
Notice that some frameworks implement this as a function, while others add the function to the array prototype.
请注意,一些框架将其作为函数实现,而另一些框架将该函数添加到数组原型中。
#2
356
Update: As @orip mentions in comments, the linked benchmark was done in 2008, so results may not be relevant for modern browsers. However, you probably need this to support non-modern browsers anyway and they probably haven't been updated since. Always test for yourself.
更新:正如@orip在评论中提到的,链接基准是在2008年完成的,所以结果可能与现代浏览器无关。但是,无论如何,您可能需要它来支持非现代浏览器,它们可能从那以后就没有更新过。总是为自己测试。
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:
正如其他人所说,通过数组进行迭代可能是最好的方法,但是已经证明,减少while循环是在JavaScript中迭代的最快方式。因此,您可能想重写代码如下:
function contains(a, obj) {
var i = a.length;
while (i--) {
if (a[i] === obj) {
return true;
}
}
return false;
}
Of course, you may as well extend Array prototype:
当然,你也可以扩展数组原型:
Array.prototype.contains = function(obj) {
var i = this.length;
while (i--) {
if (this[i] === obj) {
return true;
}
}
return false;
}
And now you can simply use the following:
现在你可以简单地使用以下方法:
alert([1, 2, 3].contains(2)); // => true
alert([1, 2, 3].contains('2')); // => false
#3
149
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."
indexOf可能,但它是“ECMA-262标准的JavaScript扩展;因此,它可能不会出现在标准的其他实现中。
Example:
例子:
[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 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).
AFAICS Microsoft没有提供某种替代方法,但是如果您愿意,可以向Internet Explorer(以及不支持indexOf的其他浏览器)中的数组添加类似的功能,正如谷歌快速搜索所显示的(例如,这个)。
#4
125
ECMAScript 7 introduces Array.prototype.includes
.
ECMAScript 7 Array.prototype.includes介绍。
It can be used like this:
它可以这样使用:
[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false
It also accepts an optional second argument fromIndex
:
它还接受可选的第二个参数fromIndex:
[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true
Unlike indexOf
, which uses Strict Equality Comparison, includes
compares using SameValueZero equality algorithm. That means that you can detect if an array includes a NaN
:
与使用严格相等比较的indexOf不同,indexOf使用samevalue0相等算法进行比较。这意味着您可以检测一个数组是否包含NaN:
[1, 2, NaN].includes(NaN); // true
Also unlike indexOf
, includes
does not skip missing indices:
也不像indexOf, include不跳过缺失指标:
new Array(5).includes(undefined); // true
Currently it's still a draft but can be polyfilled to make it work on all browsers.
目前它仍然是一个草案,但是可以进行多填充,以便在所有浏览器上都能运行。
#5
95
b
is the value, and a
is the array. It returns true
or false
:
b是值,a是数组。它返回真或假:
function(a, b) {
return a.indexOf(b) != -1
}
#6
65
Here's a JavaScript 1.6 compatible implementation of Array.indexOf
:
以下是与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;
};
}
#7
46
Use:
使用:
function isInArray(array, search)
{
return array.indexOf(search) >= 0;
}
// Usage
if(isInArray(my_array, "my_value"))
{
//...
}
#8
38
Extending the JavaScript Array
object is a really bad idea because you introduce new properties (your custom methods) into for-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.
扩展JavaScript数组对象是一个非常糟糕的想法,因为您将新的属性(您的自定义方法)引入到forin循环中,从而打破现有的脚本。几年前,原型库的作者不得不重新设计他们的库实现来删除这类东西。
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.
如果您不需要担心与页面上运行的其他JavaScript的兼容性,那么请使用它,否则,我建议使用更笨拙、但更安全的独立函数解决方案。
#9
32
You can use Array.prototype.some()
您可以使用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
Upside to this is that the iteration is aborted once the element is found so unnecessary iteration cycles are saved.
这样做的好处是,一旦找到元素,迭代将被终止,因此不必要的迭代周期将被保存。
One thing to note is that some()
is not present in all js versions: (from the website)
需要注意的一点是,some()并非出现在所有js版本中:(来自网站)
some was added to the ECMA-262 standard in the 5th edition; as such it may not be present in all implementations of the standard
在第五版的ECMA-262标准中增加了一些;因此,它可能不会出现在标准的所有实现中
You can use it in Node.js without any issue. If you need to support all browsers then there's this polyfill (from the same link):
您可以在Node中使用它。js没有任何问题。如果你需要支持所有浏览器,那么就有这个polyfill(来自同一个链接):
if (!Array.prototype.some)
{
Array.prototype.some = function(fun /*, thisArg */)
{
'use strict';
if (this === void 0 || this === null)
throw new TypeError();
var t = Object(this);
var len = t.length >>> 0;
if (typeof fun !== 'function')
throw new TypeError();
var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
for (var i = 0; i < len; i++)
{
if (i in t && fun.call(thisArg, t[i], i, t))
return true;
}
return false;
};
}
#10
21
One-liner:
一行程序:
function contains(arr, x) {
return arr.filter(function(elem) { return elem == x }).length > 0;
}
#11
20
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 array
a Map to do lookups using a hash function.
考虑一下,如果您多次调用这个函数,那么使用关联数组映射来使用散列函数进行查找的效率要高得多。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
#12
19
I use the following:
我使用下面的:
Array.prototype.contains = function (v) {
return this.indexOf(v) > -1;
}
var a = [ 'foo', 'bar' ];
a.contains('foo'); // true
a.contains('fox'); // false
#13
15
function contains(a, obj) {
return a.some(function(element){return element == obj;})
}
Array.prototype.some() was added to the ECMA-262 standard in the 5th edition
在第5版中,将some()添加到ECMA-262标准中
#14
12
A hopefully faster bidirectional indexOf
/ lastIndexOf
alternative
一个有望更快的双向索引/ lastIndexOf替代
2015
While the new method includes is very nice, the support is basically zero for now.
虽然新方法include非常好,但目前支持基本为零。
It's long time that I was thinking of way to replace the slow indexOf/lastIndexOf functions.
很长一段时间以来,我一直在思考如何取代缓慢的/lastIndexOf函数。
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.
看看上面的答案,我们已经找到了一种表演的方式。我选择了@Damir Zekic发布的包含函数,它应该是最快的。但报告也指出,这些基准是2008年制定的,因此已经过时。
I also prefer while
over for
, but for not a specific reason I ended writing the function with a for loop. It could be also done with a while --
.
我也喜欢while循环,但是由于没有特定的原因,我结束了用for循环来编写函数。这也可以在一段时间内完成。
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 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.
当你知道你只推了一个带有值的数组时,使用lastIndexOf可能是最好的解决方案,但是如果你不得不遍历大数组,结果可能是无处不在,这可能是一个可靠的解决方案,可以让事情变得更快。
Bidirectional indexOf/lastIndexOf
双向indexOf / lastIndexOf
function bidirectionalIndexOf(a, b, c, d, e){
for(c=a.length,d=c*1; c--; ){
if(a[c]==b) return c; //or this[c]===b
if(a[e=d-1-c]==b) return e; //or a[e=d-1-c]===b
}
return -1
}
//Usage
bidirectionalIndexOf(array,'value');
Performance test
http://jsperf.com/bidirectionalindexof
http://jsperf.com/bidirectionalindexof
As test I created an array with 100k entries.
作为测试,我创建了一个包含100k条目的数组。
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 the indexOf & lastIndexOf output (so basically true
with the index
and false
with -1
). That shouldn't harm it.
注意:如您所见,我稍微修改了contains函数,以反映输出的indexOf & lastIndexOf(因此索引基本为真,-1为假)。不应该伤害它。
The array prototype variant
Object.defineProperty(Array.prototype,'bidirectionalIndexOf',{value:function(b,c,d,e){
for(c=this.length,d=c*1; c--; ){
if(this[c]==b) return c; //or this[c]===b
if(this[e=d-1-c] == b) return e; //or this[e=d-1-c]===b
}
return -1
},writable:false, enumerable:false});
// Usage
array.bidirectionalIndexOf('value');
The function can also be easily modified to return true or false or even the object, string or whatever it is.
还可以很容易地修改函数以返回true或false,甚至对象、字符串或其他内容。
And here is the while
variant:
这里是while变体:
function bidirectionalIndexOf(a, b, c, d){
c=a.length; d=c-1;
while(c--){
if(b===a[c]) return c;
if(b===a[d-c]) return d-c;
}
return c
}
// Usage
bidirectionalIndexOf(array,'value');
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.
这里有一个复杂的例子,每次迭代执行三次检查,但是这只有在长时间的计算中才能实现,因为计算会导致代码的缓慢。
http://jsperf.com/bidirectionalindexof/2
http://jsperf.com/bidirectionalindexof/2
#15
10
If you are checking repeatedly for existence of an object in an array you should maybe look into
如果您正在反复检查数组中是否存在一个对象,那么您应该进行检查
- Keeping the array sorted at all times by doing insertion sort in your array (put new objects in on the right place)
- 通过在数组中执行插入排序,始终保持数组的排序(将新对象放在正确的位置)
- Make updating objects as remove+sorted insert operation and
- 使更新对象为删除+排序插入操作和
- Use a binary search lookup in your
contains(a, obj)
. - 在包含(a, obj)中使用二进制搜索查找。
#16
10
function inArray(elem,array)
{
var len = array.length;
for(var i = 0 ; i < len;i++)
{
if(array[i] == elem){return i;}
}
return -1;
}
Returns array index if found, or -1 if not found
返回数组索引,如果未找到,则返回-1。
#17
9
We use this snippet (works with objects, arrays, strings):
我们使用这个代码片段(适用于对象、数组、字符串):
/*
* @function
* @name Object.prototype.inArray
* @description Extend Object prototype within inArray function
*
* @param {mix} needle - Search-able needle
* @param {bool} searchInKey - Search needle in keys?
*
*/
Object.defineProperty(Object.prototype, 'inArray',{
value: function(needle, searchInKey){
var object = this;
if( Object.prototype.toString.call(needle) === '[object Object]' ||
Object.prototype.toString.call(needle) === '[object Array]'){
needle = JSON.stringify(needle);
}
return Object.keys(object).some(function(key){
var value = object[key];
if( Object.prototype.toString.call(value) === '[object Object]' ||
Object.prototype.toString.call(value) === '[object Array]'){
value = JSON.stringify(value);
}
if(searchInKey){
if(value === needle || key === needle){
return true;
}
}else{
if(value === needle){
return true;
}
}
});
},
writable: true,
configurable: true,
enumerable: false
});
Usage:
用法:
var a = {one: "first", two: "second", foo: {three: "third"}};
a.inArray("first"); //true
a.inArray("foo"); //false
a.inArray("foo", true); //true - search by keys
a.inArray({three: "third"}); //true
var b = ["one", "two", "three", "four", {foo: 'val'}];
b.inArray("one"); //true
b.inArray('foo'); //false
b.inArray({foo: 'val'}) //true
b.inArray("{foo: 'val'}") //false
var c = "String";
c.inArray("S"); //true
c.inArray("s"); //false
c.inArray("2", true); //true
c.inArray("20", true); //false
#18
8
Use lodash's some function.
使用lodash的一些功能。
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.
需求:建议使用最简洁有效的方法来确定一个JavaScript数组是否包含一个对象。
Accepted Answer:
答:接受
$.inArray({'b': 2}, [{'a': 1}, {'b': 2}])
> -1
My recommendation:
我的建议:
_.some([{'a': 1}, {'b': 2}], {'b': 2})
> true
Notes:
注:
$.inArray works fine for determining whether a scalar value exists in an array of scalars...
美元。inArray用于确定标量值是否存在于标量数组中。
$.inArray(2, [1,2])
> 1
... 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:
为了同时处理标量和对象,您可以这样做:
(_.isObject(item)) ? _.some(ary, item) : (_.indexOf(ary, item) > -1)
#19
7
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 do table[x]!==undefined
or ===undefined
:
虽然array.indexOf(x)!=-1是最简洁的方法(非internet Explorer浏览器已经支持了十多年……),它不是O(1),而是O(N),这很糟糕。如果你的数组不会改变,你可以将你的数组转换成一个hashtable,然后做table[x]!= =未定义或= = =定义:
Array.prototype.toTable = function() {
var t = {};
this.forEach(function(x){t[x]=true});
return t;
}
Demo:
演示:
var toRemove = [2,4].toTable();
[1,2,3,4,5].filter(function(x){return toRemove[x]===undefined})
(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.)
(不幸的是,您可以创建一个Array.prototype。包含“冻结”数组并在其中存储哈希表。_cache在两行中,如果您选择稍后编辑数组,则会得到错误的结果。JavaScript没有足够的钩子让你保持这个状态,不像Python)
#20
6
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.
如果您正在使用JavaScript 1.6或更高版本(Firefox 1.5或更高版本),您可以使用Array.indexOf。否则,我认为您将最终得到与您的原始代码类似的东西。
#21
6
ECMAScript 6 has an elegant proposal on find.
ECMAScript 6有一个优雅的发现建议。
The find method executes the callback function once for each element present in the array until it finds one where callback returns a true value. If such an element is found, find immediately returns the value of that element. Otherwise, find returns undefined. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.
find方法对数组中出现的每个元素执行一次回调函数,直到找到回调返回真实值的元素为止。如果找到这样的元素,则find立即返回该元素的值。否则,找到返回定义。回调仅用于已分配值的数组的索引;对于已删除或从未分配值的索引,不调用它。
Here is the MDN documentation on that.
这是MDN文档。
The find functionality works like this.
find功能是这样工作的。
function isPrime(element, index, array) {
var start = 2;
while (start <= Math.sqrt(element)) {
if (element % start++ < 1) return false;
}
return (element > 1);
}
console.log( [4, 6, 8, 12].find(isPrime) ); // Undefined, not found
console.log( [4, 5, 8, 12].find(isPrime) ); // 5
You can use this in ECMAScript 5 and below by defining the function.
通过定义函数,您可以在ECMAScript 5和下面使用它。
if (!Array.prototype.find) {
Object.defineProperty(Array.prototype, 'find', {
enumerable: false,
configurable: true,
writable: true,
value: function(predicate) {
if (this == null) {
throw new TypeError('Array.prototype.find called on null or undefined');
}
if (typeof predicate !== 'function') {
throw new TypeError('predicate must be a function');
}
var list = Object(this);
var length = list.length >>> 0;
var thisArg = arguments[1];
var value;
for (var i = 0; i < length; i++) {
if (i in list) {
value = list[i];
if (predicate.call(thisArg, value, i, list)) {
return value;
}
}
}
return undefined;
}
});
}
#22
6
Solution that works in all modern browsers:
适用于所有现代浏览器的解决方案:
function contains(arr, obj) {
const stringifiedObj = JSON.stringify(obj); // Cache our object to not call `JSON.stringify` on every iteration
return arr.some(item => JSON.stringify(item) === stringifiedObj);
}
Usage:
用法:
contains([{a: 1}, {a: 2}], {a: 1}); // true
IE6+ solution:
IE6 +解决方案:
function contains(arr, obj) {
var stringifiedObj = JSON.stringify(obj)
return arr.some(function (item) {
return JSON.stringify(item) === stringifiedObj;
});
}
// .some polyfill, not needed for IE9+
if (!('some' in Array.prototype)) {
Array.prototype.some = function (tester, that /*opt*/) {
for (var i = 0, n = this.length; i < n; i++) {
if (i in this && tester.call(that, this[i], i, this)) return true;
} return false;
};
}
Usage:
用法:
contains([{a: 1}, {a: 2}], {a: 1}); // true
Why to use JSON.stringify
?
Array.indexOf
and Array.includes
(as well as most of the answers here) only compare by reference and not by value.
数组中。indexOf和数组。包含(以及这里的大多数答案)只通过引用而不是值进行比较。
[{a: 1}, {a: 2}].includes({a: 1});
// false, because {a: 1} is a new object
Bonus
Non-optimized ES6 one-liner:
未经优化ES6一行程序:
[{a: 1}, {a: 2}].some(item => JSON.stringify(item) === JSON.stringify({a: 1));
// true
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
注意:如果键的顺序相同,按值对对象进行比较会更好,因此为了安全起见,您可以先对键进行排序,并使用如下包:https://www.npmjs.com/package/sort-keys
Updated the contains
function with a perf optimization. Thanks itinance for pointing it out.
使用perf优化升级包含函数。谢谢你指出来。
#23
5
Use:
使用:
var myArray = ['yellow', 'orange', 'red'] ;
alert(!!~myArray.indexOf('red')); //true
演示
To know exactly what the tilde
~
do at this point, refer to this question What does a tilde do when it precedes an expression?.
要确切地知道倾斜~在这一点上做什么,请参考这个问题:倾斜在表达式之前做什么?
#24
3
Use:
使用:
Array.prototype.contains = function(x){
var retVal = -1;
// x is a primitive type
if(["string","number"].indexOf(typeof x)>=0 ){ retVal = this.indexOf(x);}
// x is a function
else if(typeof x =="function") for(var ix in this){
if((this[ix]+"")==(x+"")) retVal = ix;
}
//x is an object...
else {
var sx=JSON.stringify(x);
for(var ix in this){
if(typeof this[ix] =="object" && JSON.stringify(this[ix])==sx) retVal = ix;
}
}
//Return False if -1 else number if numeric otherwise string
return (retVal === -1)?false : ( isNaN(+retVal) ? retVal : +retVal);
}
I know it's not the best way to go, but since there is no native IComparable way to interact between objects, I guess this is as close as you can get to compare two entities in an array. Also, extending Array object might not be a wise thing to do, but sometimes it's OK (if you are aware of it and the trade-off).
我知道这不是最好的方法,但是因为没有本地的可编程的方式在对象之间进行交互,所以我想这是比较接近的,可以比较数组中的两个实体。此外,扩展数组对象可能不是一件明智的事情,但有时它是可以的(如果您知道它和权衡的话)。
#25
3
One can use Set that has the method "has()":
可以使用方法为“has()”的Set:
function contains(arr, obj) {
var proxy = new Set(arr);
if (proxy.has(obj))
return true;
else
return false;
}
var arr = ['Happy', 'New', 'Year'];
console.log(contains(arr, 'Happy'));
#26
3
You can also use this trick:
你也可以使用这个技巧:
var arrayContains = function(object) {
return (serverList.filter(function(currentObject) {
if (currentObject === object) {
return currentObject
}
else {
return false;
}
}).length > 0) ? true : false
}
#27
2
Here's how Prototype does it:
下面是Prototype的工作原理:
/**
* 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 — 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;
}
Also see here for how they hook it up.
这里也可以看到它们是如何连接起来的。
#28
2
As others have mentioned you can use Array.indexOf
, but it isn't available in all browsers. Here's the code from https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf to make it work the same in older browsers.
正如其他人提到的,您可以使用数组。indexOf,但并不是所有浏览器都可以使用。下面是来自https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf的代码,以使它在旧的浏览器中同样工作。
indexOf is a recent addition to the ECMA-262 standard; as such it may not be present in all browsers. You can work around this by inserting the following code at the beginning of your scripts, allowing use of indexOf in implementations which do not natively support it. This algorithm is exactly the one specified in ECMA-262, 5th edition, assuming Object, TypeError, Number, Math.floor, Math.abs, and Math.max have their original value.
indexOf是最近添加的ECMA-262标准;因此,它可能不会出现在所有的浏览器中。您可以通过在脚本的开头插入以下代码来解决这个问题,允许在不支持它的实现中使用indexOf。这个算法正是在第五版ECMA-262中指定的算法,假设对象、类型错误、数字、数学。地板上,数学。abs、和数学。max有其原始价值。
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
"use strict";
if (this == null) {
throw new TypeError();
}
var t = Object(this);
var len = t.length >>> 0;
if (len === 0) {
return -1;
}
var n = 0;
if (arguments.length > 1) {
n = Number(arguments[1]);
if (n != n) { // shortcut for verifying if it's NaN
n = 0;
} else if (n != 0 && n != Infinity && n != -Infinity) {
n = (n > 0 || -1) * Math.floor(Math.abs(n));
}
}
if (n >= len) {
return -1;
}
var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
for (; k < len; k++) {
if (k in t && t[k] === searchElement) {
return k;
}
}
return -1;
}
}
#29
2
By no means the best, but I was just getting creative and adding to the repertoire.
这绝不是最好的,但我只是变得有创意,并增加剧目。
Do not use this
Object.defineProperty(Array.prototype, 'exists', {
value: function(element, index) {
var index = index || 0
return index === this.length ? -1 : this[index] === element ? index : this.exists(element, ++index)
}
})
// Outputs 1
console.log(['one', 'two'].exists('two'));
// Outputs -1
console.log(['one', 'two'].exists('three'));
console.log(['one', 'two', 'three', 'four'].exists('four'));
#30
2
- Either use Array.indexOf(Object).
- 要么使用Array.indexOf(对象)。
- With ECMA 7 one can use the Array.includes(Object).
- 使用ECMA 7可以使用array. include(对象)。
-
With ECMA 6 you can use Array.find(FunctionName) where FunctionName is a user defined function to search for the object in the array.
使用ECMA 6,可以使用array. find(FunctionName),其中FunctionName是用户定义的函数,用于搜索数组中的对象。
Hope this helps!
希望这可以帮助!
#1
3609
Current browsers have Array#includes
, which does exactly that, is widely supported, and has a polyfill for older browsers.
当前的浏览器有数组#include,它确实做到了这一点,得到了广泛的支持,并且有一个用于旧浏览器的polyfill。
You can also use Array#indexOf
, which is less direct, but doesn't require Polyfills for out of date browsers.
您还可以使用数组#indexOf,它不太直接,但不需要为过期浏览器填充。
jQuery offers $.inArray
, which is functionally equivalent to Array#indexOf
.
jQuery提供美元。inArray,在功能上等同于数组#indexOf。
underscore.js, a JavaScript utility library, offers _.contains(list, value)
, alias _.include(list, value)
, both of which use indexOf internally if passed a JavaScript array.
下划线。JavaScript实用程序库js提供_。包含(列表,价值),别名_。include(list, value),如果传递一个JavaScript数组,它们都在内部使用indexOf。
Some other frameworks offer similar methods:
其他一些框架提供了类似的方法:
- Dojo Toolkit:
dojo.indexOf(array, value, [fromIndex, findLast])
- Dojo Toolkit:Dojo。indexOf(数组、价值[fromIndex findLast])
- Prototype:
array.indexOf(value)
- 原型:array.indexOf(值)
- MooTools:
array.indexOf(value)
- MooTools:array.indexOf(值)
- MochiKit:
findValue(array, value)
- MochiKit:findValue(数组,值)
- MS Ajax:
array.indexOf(value)
- Ajax女士:array.indexOf(值)
- Ext:
Ext.Array.contains(array, value)
- Ext:Ext.Array。包含(数组,价值)
- Lodash:
_.includes(array, value, [from])
(is_.contains
prior 4.0.0) - Lodash:_。包含(数组,值,[from]) (is _。包含4.0.0之前)
- ECMAScript 2016:
array.includes(value)
- ECMAScript 2016:array.includes(值)
Notice that some frameworks implement this as a function, while others add the function to the array prototype.
请注意,一些框架将其作为函数实现,而另一些框架将该函数添加到数组原型中。
#2
356
Update: As @orip mentions in comments, the linked benchmark was done in 2008, so results may not be relevant for modern browsers. However, you probably need this to support non-modern browsers anyway and they probably haven't been updated since. Always test for yourself.
更新:正如@orip在评论中提到的,链接基准是在2008年完成的,所以结果可能与现代浏览器无关。但是,无论如何,您可能需要它来支持非现代浏览器,它们可能从那以后就没有更新过。总是为自己测试。
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:
正如其他人所说,通过数组进行迭代可能是最好的方法,但是已经证明,减少while循环是在JavaScript中迭代的最快方式。因此,您可能想重写代码如下:
function contains(a, obj) {
var i = a.length;
while (i--) {
if (a[i] === obj) {
return true;
}
}
return false;
}
Of course, you may as well extend Array prototype:
当然,你也可以扩展数组原型:
Array.prototype.contains = function(obj) {
var i = this.length;
while (i--) {
if (this[i] === obj) {
return true;
}
}
return false;
}
And now you can simply use the following:
现在你可以简单地使用以下方法:
alert([1, 2, 3].contains(2)); // => true
alert([1, 2, 3].contains('2')); // => false
#3
149
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."
indexOf可能,但它是“ECMA-262标准的JavaScript扩展;因此,它可能不会出现在标准的其他实现中。
Example:
例子:
[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 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).
AFAICS Microsoft没有提供某种替代方法,但是如果您愿意,可以向Internet Explorer(以及不支持indexOf的其他浏览器)中的数组添加类似的功能,正如谷歌快速搜索所显示的(例如,这个)。
#4
125
ECMAScript 7 introduces Array.prototype.includes
.
ECMAScript 7 Array.prototype.includes介绍。
It can be used like this:
它可以这样使用:
[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false
It also accepts an optional second argument fromIndex
:
它还接受可选的第二个参数fromIndex:
[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true
Unlike indexOf
, which uses Strict Equality Comparison, includes
compares using SameValueZero equality algorithm. That means that you can detect if an array includes a NaN
:
与使用严格相等比较的indexOf不同,indexOf使用samevalue0相等算法进行比较。这意味着您可以检测一个数组是否包含NaN:
[1, 2, NaN].includes(NaN); // true
Also unlike indexOf
, includes
does not skip missing indices:
也不像indexOf, include不跳过缺失指标:
new Array(5).includes(undefined); // true
Currently it's still a draft but can be polyfilled to make it work on all browsers.
目前它仍然是一个草案,但是可以进行多填充,以便在所有浏览器上都能运行。
#5
95
b
is the value, and a
is the array. It returns true
or false
:
b是值,a是数组。它返回真或假:
function(a, b) {
return a.indexOf(b) != -1
}
#6
65
Here's a JavaScript 1.6 compatible implementation of Array.indexOf
:
以下是与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;
};
}
#7
46
Use:
使用:
function isInArray(array, search)
{
return array.indexOf(search) >= 0;
}
// Usage
if(isInArray(my_array, "my_value"))
{
//...
}
#8
38
Extending the JavaScript Array
object is a really bad idea because you introduce new properties (your custom methods) into for-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.
扩展JavaScript数组对象是一个非常糟糕的想法,因为您将新的属性(您的自定义方法)引入到forin循环中,从而打破现有的脚本。几年前,原型库的作者不得不重新设计他们的库实现来删除这类东西。
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.
如果您不需要担心与页面上运行的其他JavaScript的兼容性,那么请使用它,否则,我建议使用更笨拙、但更安全的独立函数解决方案。
#9
32
You can use Array.prototype.some()
您可以使用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
Upside to this is that the iteration is aborted once the element is found so unnecessary iteration cycles are saved.
这样做的好处是,一旦找到元素,迭代将被终止,因此不必要的迭代周期将被保存。
One thing to note is that some()
is not present in all js versions: (from the website)
需要注意的一点是,some()并非出现在所有js版本中:(来自网站)
some was added to the ECMA-262 standard in the 5th edition; as such it may not be present in all implementations of the standard
在第五版的ECMA-262标准中增加了一些;因此,它可能不会出现在标准的所有实现中
You can use it in Node.js without any issue. If you need to support all browsers then there's this polyfill (from the same link):
您可以在Node中使用它。js没有任何问题。如果你需要支持所有浏览器,那么就有这个polyfill(来自同一个链接):
if (!Array.prototype.some)
{
Array.prototype.some = function(fun /*, thisArg */)
{
'use strict';
if (this === void 0 || this === null)
throw new TypeError();
var t = Object(this);
var len = t.length >>> 0;
if (typeof fun !== 'function')
throw new TypeError();
var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
for (var i = 0; i < len; i++)
{
if (i in t && fun.call(thisArg, t[i], i, t))
return true;
}
return false;
};
}
#10
21
One-liner:
一行程序:
function contains(arr, x) {
return arr.filter(function(elem) { return elem == x }).length > 0;
}
#11
20
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 array
a Map to do lookups using a hash function.
考虑一下,如果您多次调用这个函数,那么使用关联数组映射来使用散列函数进行查找的效率要高得多。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
#12
19
I use the following:
我使用下面的:
Array.prototype.contains = function (v) {
return this.indexOf(v) > -1;
}
var a = [ 'foo', 'bar' ];
a.contains('foo'); // true
a.contains('fox'); // false
#13
15
function contains(a, obj) {
return a.some(function(element){return element == obj;})
}
Array.prototype.some() was added to the ECMA-262 standard in the 5th edition
在第5版中,将some()添加到ECMA-262标准中
#14
12
A hopefully faster bidirectional indexOf
/ lastIndexOf
alternative
一个有望更快的双向索引/ lastIndexOf替代
2015
While the new method includes is very nice, the support is basically zero for now.
虽然新方法include非常好,但目前支持基本为零。
It's long time that I was thinking of way to replace the slow indexOf/lastIndexOf functions.
很长一段时间以来,我一直在思考如何取代缓慢的/lastIndexOf函数。
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.
看看上面的答案,我们已经找到了一种表演的方式。我选择了@Damir Zekic发布的包含函数,它应该是最快的。但报告也指出,这些基准是2008年制定的,因此已经过时。
I also prefer while
over for
, but for not a specific reason I ended writing the function with a for loop. It could be also done with a while --
.
我也喜欢while循环,但是由于没有特定的原因,我结束了用for循环来编写函数。这也可以在一段时间内完成。
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 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.
当你知道你只推了一个带有值的数组时,使用lastIndexOf可能是最好的解决方案,但是如果你不得不遍历大数组,结果可能是无处不在,这可能是一个可靠的解决方案,可以让事情变得更快。
Bidirectional indexOf/lastIndexOf
双向indexOf / lastIndexOf
function bidirectionalIndexOf(a, b, c, d, e){
for(c=a.length,d=c*1; c--; ){
if(a[c]==b) return c; //or this[c]===b
if(a[e=d-1-c]==b) return e; //or a[e=d-1-c]===b
}
return -1
}
//Usage
bidirectionalIndexOf(array,'value');
Performance test
http://jsperf.com/bidirectionalindexof
http://jsperf.com/bidirectionalindexof
As test I created an array with 100k entries.
作为测试,我创建了一个包含100k条目的数组。
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 the indexOf & lastIndexOf output (so basically true
with the index
and false
with -1
). That shouldn't harm it.
注意:如您所见,我稍微修改了contains函数,以反映输出的indexOf & lastIndexOf(因此索引基本为真,-1为假)。不应该伤害它。
The array prototype variant
Object.defineProperty(Array.prototype,'bidirectionalIndexOf',{value:function(b,c,d,e){
for(c=this.length,d=c*1; c--; ){
if(this[c]==b) return c; //or this[c]===b
if(this[e=d-1-c] == b) return e; //or this[e=d-1-c]===b
}
return -1
},writable:false, enumerable:false});
// Usage
array.bidirectionalIndexOf('value');
The function can also be easily modified to return true or false or even the object, string or whatever it is.
还可以很容易地修改函数以返回true或false,甚至对象、字符串或其他内容。
And here is the while
variant:
这里是while变体:
function bidirectionalIndexOf(a, b, c, d){
c=a.length; d=c-1;
while(c--){
if(b===a[c]) return c;
if(b===a[d-c]) return d-c;
}
return c
}
// Usage
bidirectionalIndexOf(array,'value');
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.
这里有一个复杂的例子,每次迭代执行三次检查,但是这只有在长时间的计算中才能实现,因为计算会导致代码的缓慢。
http://jsperf.com/bidirectionalindexof/2
http://jsperf.com/bidirectionalindexof/2
#15
10
If you are checking repeatedly for existence of an object in an array you should maybe look into
如果您正在反复检查数组中是否存在一个对象,那么您应该进行检查
- Keeping the array sorted at all times by doing insertion sort in your array (put new objects in on the right place)
- 通过在数组中执行插入排序,始终保持数组的排序(将新对象放在正确的位置)
- Make updating objects as remove+sorted insert operation and
- 使更新对象为删除+排序插入操作和
- Use a binary search lookup in your
contains(a, obj)
. - 在包含(a, obj)中使用二进制搜索查找。
#16
10
function inArray(elem,array)
{
var len = array.length;
for(var i = 0 ; i < len;i++)
{
if(array[i] == elem){return i;}
}
return -1;
}
Returns array index if found, or -1 if not found
返回数组索引,如果未找到,则返回-1。
#17
9
We use this snippet (works with objects, arrays, strings):
我们使用这个代码片段(适用于对象、数组、字符串):
/*
* @function
* @name Object.prototype.inArray
* @description Extend Object prototype within inArray function
*
* @param {mix} needle - Search-able needle
* @param {bool} searchInKey - Search needle in keys?
*
*/
Object.defineProperty(Object.prototype, 'inArray',{
value: function(needle, searchInKey){
var object = this;
if( Object.prototype.toString.call(needle) === '[object Object]' ||
Object.prototype.toString.call(needle) === '[object Array]'){
needle = JSON.stringify(needle);
}
return Object.keys(object).some(function(key){
var value = object[key];
if( Object.prototype.toString.call(value) === '[object Object]' ||
Object.prototype.toString.call(value) === '[object Array]'){
value = JSON.stringify(value);
}
if(searchInKey){
if(value === needle || key === needle){
return true;
}
}else{
if(value === needle){
return true;
}
}
});
},
writable: true,
configurable: true,
enumerable: false
});
Usage:
用法:
var a = {one: "first", two: "second", foo: {three: "third"}};
a.inArray("first"); //true
a.inArray("foo"); //false
a.inArray("foo", true); //true - search by keys
a.inArray({three: "third"}); //true
var b = ["one", "two", "three", "four", {foo: 'val'}];
b.inArray("one"); //true
b.inArray('foo'); //false
b.inArray({foo: 'val'}) //true
b.inArray("{foo: 'val'}") //false
var c = "String";
c.inArray("S"); //true
c.inArray("s"); //false
c.inArray("2", true); //true
c.inArray("20", true); //false
#18
8
Use lodash's some function.
使用lodash的一些功能。
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.
需求:建议使用最简洁有效的方法来确定一个JavaScript数组是否包含一个对象。
Accepted Answer:
答:接受
$.inArray({'b': 2}, [{'a': 1}, {'b': 2}])
> -1
My recommendation:
我的建议:
_.some([{'a': 1}, {'b': 2}], {'b': 2})
> true
Notes:
注:
$.inArray works fine for determining whether a scalar value exists in an array of scalars...
美元。inArray用于确定标量值是否存在于标量数组中。
$.inArray(2, [1,2])
> 1
... 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:
为了同时处理标量和对象,您可以这样做:
(_.isObject(item)) ? _.some(ary, item) : (_.indexOf(ary, item) > -1)
#19
7
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 do table[x]!==undefined
or ===undefined
:
虽然array.indexOf(x)!=-1是最简洁的方法(非internet Explorer浏览器已经支持了十多年……),它不是O(1),而是O(N),这很糟糕。如果你的数组不会改变,你可以将你的数组转换成一个hashtable,然后做table[x]!= =未定义或= = =定义:
Array.prototype.toTable = function() {
var t = {};
this.forEach(function(x){t[x]=true});
return t;
}
Demo:
演示:
var toRemove = [2,4].toTable();
[1,2,3,4,5].filter(function(x){return toRemove[x]===undefined})
(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.)
(不幸的是,您可以创建一个Array.prototype。包含“冻结”数组并在其中存储哈希表。_cache在两行中,如果您选择稍后编辑数组,则会得到错误的结果。JavaScript没有足够的钩子让你保持这个状态,不像Python)
#20
6
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.
如果您正在使用JavaScript 1.6或更高版本(Firefox 1.5或更高版本),您可以使用Array.indexOf。否则,我认为您将最终得到与您的原始代码类似的东西。
#21
6
ECMAScript 6 has an elegant proposal on find.
ECMAScript 6有一个优雅的发现建议。
The find method executes the callback function once for each element present in the array until it finds one where callback returns a true value. If such an element is found, find immediately returns the value of that element. Otherwise, find returns undefined. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.
find方法对数组中出现的每个元素执行一次回调函数,直到找到回调返回真实值的元素为止。如果找到这样的元素,则find立即返回该元素的值。否则,找到返回定义。回调仅用于已分配值的数组的索引;对于已删除或从未分配值的索引,不调用它。
Here is the MDN documentation on that.
这是MDN文档。
The find functionality works like this.
find功能是这样工作的。
function isPrime(element, index, array) {
var start = 2;
while (start <= Math.sqrt(element)) {
if (element % start++ < 1) return false;
}
return (element > 1);
}
console.log( [4, 6, 8, 12].find(isPrime) ); // Undefined, not found
console.log( [4, 5, 8, 12].find(isPrime) ); // 5
You can use this in ECMAScript 5 and below by defining the function.
通过定义函数,您可以在ECMAScript 5和下面使用它。
if (!Array.prototype.find) {
Object.defineProperty(Array.prototype, 'find', {
enumerable: false,
configurable: true,
writable: true,
value: function(predicate) {
if (this == null) {
throw new TypeError('Array.prototype.find called on null or undefined');
}
if (typeof predicate !== 'function') {
throw new TypeError('predicate must be a function');
}
var list = Object(this);
var length = list.length >>> 0;
var thisArg = arguments[1];
var value;
for (var i = 0; i < length; i++) {
if (i in list) {
value = list[i];
if (predicate.call(thisArg, value, i, list)) {
return value;
}
}
}
return undefined;
}
});
}
#22
6
Solution that works in all modern browsers:
适用于所有现代浏览器的解决方案:
function contains(arr, obj) {
const stringifiedObj = JSON.stringify(obj); // Cache our object to not call `JSON.stringify` on every iteration
return arr.some(item => JSON.stringify(item) === stringifiedObj);
}
Usage:
用法:
contains([{a: 1}, {a: 2}], {a: 1}); // true
IE6+ solution:
IE6 +解决方案:
function contains(arr, obj) {
var stringifiedObj = JSON.stringify(obj)
return arr.some(function (item) {
return JSON.stringify(item) === stringifiedObj;
});
}
// .some polyfill, not needed for IE9+
if (!('some' in Array.prototype)) {
Array.prototype.some = function (tester, that /*opt*/) {
for (var i = 0, n = this.length; i < n; i++) {
if (i in this && tester.call(that, this[i], i, this)) return true;
} return false;
};
}
Usage:
用法:
contains([{a: 1}, {a: 2}], {a: 1}); // true
Why to use JSON.stringify
?
Array.indexOf
and Array.includes
(as well as most of the answers here) only compare by reference and not by value.
数组中。indexOf和数组。包含(以及这里的大多数答案)只通过引用而不是值进行比较。
[{a: 1}, {a: 2}].includes({a: 1});
// false, because {a: 1} is a new object
Bonus
Non-optimized ES6 one-liner:
未经优化ES6一行程序:
[{a: 1}, {a: 2}].some(item => JSON.stringify(item) === JSON.stringify({a: 1));
// true
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
注意:如果键的顺序相同,按值对对象进行比较会更好,因此为了安全起见,您可以先对键进行排序,并使用如下包:https://www.npmjs.com/package/sort-keys
Updated the contains
function with a perf optimization. Thanks itinance for pointing it out.
使用perf优化升级包含函数。谢谢你指出来。
#23
5
Use:
使用:
var myArray = ['yellow', 'orange', 'red'] ;
alert(!!~myArray.indexOf('red')); //true
演示
To know exactly what the tilde
~
do at this point, refer to this question What does a tilde do when it precedes an expression?.
要确切地知道倾斜~在这一点上做什么,请参考这个问题:倾斜在表达式之前做什么?
#24
3
Use:
使用:
Array.prototype.contains = function(x){
var retVal = -1;
// x is a primitive type
if(["string","number"].indexOf(typeof x)>=0 ){ retVal = this.indexOf(x);}
// x is a function
else if(typeof x =="function") for(var ix in this){
if((this[ix]+"")==(x+"")) retVal = ix;
}
//x is an object...
else {
var sx=JSON.stringify(x);
for(var ix in this){
if(typeof this[ix] =="object" && JSON.stringify(this[ix])==sx) retVal = ix;
}
}
//Return False if -1 else number if numeric otherwise string
return (retVal === -1)?false : ( isNaN(+retVal) ? retVal : +retVal);
}
I know it's not the best way to go, but since there is no native IComparable way to interact between objects, I guess this is as close as you can get to compare two entities in an array. Also, extending Array object might not be a wise thing to do, but sometimes it's OK (if you are aware of it and the trade-off).
我知道这不是最好的方法,但是因为没有本地的可编程的方式在对象之间进行交互,所以我想这是比较接近的,可以比较数组中的两个实体。此外,扩展数组对象可能不是一件明智的事情,但有时它是可以的(如果您知道它和权衡的话)。
#25
3
One can use Set that has the method "has()":
可以使用方法为“has()”的Set:
function contains(arr, obj) {
var proxy = new Set(arr);
if (proxy.has(obj))
return true;
else
return false;
}
var arr = ['Happy', 'New', 'Year'];
console.log(contains(arr, 'Happy'));
#26
3
You can also use this trick:
你也可以使用这个技巧:
var arrayContains = function(object) {
return (serverList.filter(function(currentObject) {
if (currentObject === object) {
return currentObject
}
else {
return false;
}
}).length > 0) ? true : false
}
#27
2
Here's how Prototype does it:
下面是Prototype的工作原理:
/**
* 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 — 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;
}
Also see here for how they hook it up.
这里也可以看到它们是如何连接起来的。
#28
2
As others have mentioned you can use Array.indexOf
, but it isn't available in all browsers. Here's the code from https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf to make it work the same in older browsers.
正如其他人提到的,您可以使用数组。indexOf,但并不是所有浏览器都可以使用。下面是来自https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf的代码,以使它在旧的浏览器中同样工作。
indexOf is a recent addition to the ECMA-262 standard; as such it may not be present in all browsers. You can work around this by inserting the following code at the beginning of your scripts, allowing use of indexOf in implementations which do not natively support it. This algorithm is exactly the one specified in ECMA-262, 5th edition, assuming Object, TypeError, Number, Math.floor, Math.abs, and Math.max have their original value.
indexOf是最近添加的ECMA-262标准;因此,它可能不会出现在所有的浏览器中。您可以通过在脚本的开头插入以下代码来解决这个问题,允许在不支持它的实现中使用indexOf。这个算法正是在第五版ECMA-262中指定的算法,假设对象、类型错误、数字、数学。地板上,数学。abs、和数学。max有其原始价值。
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
"use strict";
if (this == null) {
throw new TypeError();
}
var t = Object(this);
var len = t.length >>> 0;
if (len === 0) {
return -1;
}
var n = 0;
if (arguments.length > 1) {
n = Number(arguments[1]);
if (n != n) { // shortcut for verifying if it's NaN
n = 0;
} else if (n != 0 && n != Infinity && n != -Infinity) {
n = (n > 0 || -1) * Math.floor(Math.abs(n));
}
}
if (n >= len) {
return -1;
}
var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
for (; k < len; k++) {
if (k in t && t[k] === searchElement) {
return k;
}
}
return -1;
}
}
#29
2
By no means the best, but I was just getting creative and adding to the repertoire.
这绝不是最好的,但我只是变得有创意,并增加剧目。
Do not use this
Object.defineProperty(Array.prototype, 'exists', {
value: function(element, index) {
var index = index || 0
return index === this.length ? -1 : this[index] === element ? index : this.exists(element, ++index)
}
})
// Outputs 1
console.log(['one', 'two'].exists('two'));
// Outputs -1
console.log(['one', 'two'].exists('three'));
console.log(['one', 'two', 'three', 'four'].exists('four'));
#30
2
- Either use Array.indexOf(Object).
- 要么使用Array.indexOf(对象)。
- With ECMA 7 one can use the Array.includes(Object).
- 使用ECMA 7可以使用array. include(对象)。
-
With ECMA 6 you can use Array.find(FunctionName) where FunctionName is a user defined function to search for the object in the array.
使用ECMA 6,可以使用array. find(FunctionName),其中FunctionName是用户定义的函数,用于搜索数组中的对象。
Hope this helps!
希望这可以帮助!