提问人:brad 提问时间:10/26/2008 最后编辑:armandinobrad 更新时间:7/27/2023 访问量:3515750
如何检查数组是否包含 JavaScript 中的值?
How do I check if an array includes a value in 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
答:
如果您使用的是 JavaScript 1.6 或更高版本(Firefox 1.5 或更高版本),则可以使用 Array.indexOf。否则,我认为你最终会得到与原始代码相似的东西。
index,
但它是“ECMA-262 标准的 JavaScript 扩展;因此,它可能不存在于该标准的其他实现中。
例:
[1, 2, 3].indexOf(1) => 0
["foo", "bar", "baz"].indexOf("bar") => 1
[1, 2, 3].indexOf(4) => -1
AFAICS Microsoft 没有提供某种替代方案,但如果您愿意,您可以向 Internet Explorer(以及其他不支持的浏览器)中的数组添加类似的功能,正如快速 Google 搜索所显示的那样(例如,这个)。indexOf
2019 年更新:这个答案来自 2008 年(11 岁!),与现代 JS 使用无关。承诺的性能改进是基于当时在浏览器中完成的基准测试。它可能与现代 JS 执行上下文无关。如果您需要一个简单的解决方案,请寻找其他答案。如果您需要最佳性能,请在相关执行环境中进行基准测试。
正如其他人所说,通过数组进行迭代可能是最好的方法,但已经证明,减少循环是在 JavaScript 中迭代的最快方法。因此,您可能需要按如下方式重写代码:while
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
评论
下面是一个 JavaScript 1.6 兼容的实现:Array.indexOf
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;
};
}
评论
[].indexOf
Array.prototype.indexOf
[].indexOf
indexOf
Array.prototype.indexOf
[].indexOf === Array.prototype.indexOf
[].indexOf !== Array.indexOf
扩展 JavaScript 对象是一个非常糟糕的主意,因为您将新属性(自定义方法)引入循环中,这可能会破坏现有脚本。几年前,Prototype 库的作者不得不重新设计他们的库实现,以删除这种东西。Array
for-in
如果你不需要担心与页面上运行的其他JavaScript的兼容性,那就去做吧,否则,我建议你使用更笨拙但更安全的独立函数解决方案。
评论
/**
* 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;
}
另请参阅此处,了解他们如何连接它。
现代浏览器有 Array#includes
,它正是这样做的,并且除了 IE 之外,所有人都广泛支持:
console.log(['joe', 'jane', 'mary'].includes('jane')); // true
你也可以使用 Array#indexOf
,它不太直接,但对于过时的浏览器不需要 polyfills。
console.log(['joe', 'jane', 'mary'].indexOf('jane') >= 0); // true
许多框架也提供了类似的方法:
- jQuery:
$.inArray(值,数组,[fromIndex])
- 下划线.js:
_.contains(数组,值)(
也别名为 和_.include
_.includes
) - Dojo 工具包:
dojo.indexOf(array, value, [fromIndex, findLast])
- 原型:
array.indexOf(value)
- MooTools:
array.indexOf(值)
- MochiKit:
findValue(数组,值)
- MS Ajax:
array.indexOf(值)
- Ext
:Ext.Array.contains(数组,值)
- Lodash:
_.includes(array, value, [from]) (低于 4.0.0)
_.contains
- Ramda:
R.includes(值, 数组)
请注意,一些框架将其实现为函数,而其他框架则将该函数添加到数组原型中。
评论
Array.include
array.indexOf(object) != -1
inArray
对于返回元素索引的函数来说,这是一个可怕的名称,如果它不存在的话。我希望返回一个布尔值。-1
开箱即用地想一想,如果你多次进行此调用,那么使用关联数组 Map 使用哈希函数进行查找的效率要高得多。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
只是另一种选择
// usage: if ( ['a','b','c','d'].contains('b') ) { ... }
Array.prototype.contains = function(value){
for (var key in this)
if (this[key] === value) return true;
return false;
}
请小心,因为使用自定义方法重载 javascript 数组对象可能会破坏其他 javascript 的行为,从而导致意外行为。
评论
for in
for in
如果你反复检查数组中是否存在一个对象,你可能应该研究一下
- 通过在数组中进行插入排序(将新对象放在正确的位置)始终保持数组排序
- 将更新对象设置为删除+排序的插入操作和
- 在 .
contains(a, obj)
评论
按照字面:
(使用 Firefox v3.6,但如前所述
(但是,下面的用法可能支持这个目的!也就是说,通过属性索引枚举实际存在的数组元素(但是,特别是,数组属性不会在属性列表中枚举!for-in
for-in
length
for-in
(拖放以下完整的 URI 以进行即时模式浏览器测试。
JavaScript的:
function ObjInRA(ra){var has=false; for(i in ra){has=true; break;} return has;}
function check(ra){
return ['There is ',ObjInRA(ra)?'an':'NO',' object in [',ra,'].'].join('')
}
alert([
check([{}]), check([]), check([,2,3]),
check(['']), '\t (a null string)', check([,,,])
].join('\n'));
其中显示:
There is an object in [[object Object]].
There is NO object in [].
There is an object in [,2,3].
There is an object in [].
(a null string)
There is NO object in [,,].
皱纹:如果寻找“特定”对象,请考虑:
JavaScript的:alert({}!={}); alert({}!=={});
因此:
JavaScript的:
obj = {prop:"value"};
ra1 = [obj];
ra2 = [{prop:"value"}];
alert(ra1[0] == obj);
alert(ra2[0] == obj);
通常被认为是“包含”作为文字实体。ra2
obj
{prop:"value"}
一个非常粗糙、简陋、幼稚(如代码需要资格增强)的解决方案:
JavaScript的:
obj={prop:"value"}; ra2=[{prop:"value"}];
alert(
ra2 . toSource() . indexOf( obj.toSource().match(/^.(.*).$/)[1] ) != -1 ?
'found' :
'missing' );
参见参考文献:在 JavaScript 数组中搜索对象。
用:
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);
}
我知道这不是最好的方法,但由于没有原生的 IComparable 方式来在对象之间进行交互,我想这与比较数组中的两个实体一样接近。此外,扩展 Array 对象可能不是一件明智的事情,但有时它是可以的(如果你意识到它和权衡)。
评论
contains([{ a: 1, b: 2 }], { b: 2, a: 1 })
假设您定义了一个数组,如下所示:
const array = [1, 2, 3, 4]
以下是检查其中是否有的三种方法。它们都返回 either 或 。3
true
false
Native Array 方法(自 ES2016 起)(兼容性表)
array.includes(3) // true
作为自定义数组方法(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
评论
虽然这是最简洁的方法(并且十多年来一直被非 Internet Explorer 浏览器支持...),但它不是 O(1),而是 O(N),这很糟糕。如果你的数组不会改变,你可以将你的数组转换为哈希表,然后执行或:array.indexOf(x)!=-1
table[x]!==undefined
===undefined
Array.prototype.toTable = function() {
var t = {};
this.forEach(function(x){t[x]=true});
return t;
}
演示:
var toRemove = [2,4].toTable();
[1,2,3,4,5].filter(function(x){return toRemove[x]===undefined})
(不幸的是,虽然您可以创建一个 Array.prototype.contains 来“冻结”数组并将哈希表存储在 this._cache 中的两行中,但如果您选择稍后编辑数组,这将产生错误的结果。JavaScript 没有足够的钩子来让你保持这种状态,这与 Python 不同。
function inArray(elem,array)
{
var len = array.length;
for(var i = 0 ; i < len;i++)
{
if(array[i] == elem){return i;}
}
return -1;
}
如果找到,则返回数组索引,如果未找到,则返回 -1
类似的事情:通过“搜索lambda”找到第一个元素:
Array.prototype.find = function(search_lambda) {
return this[this.map(search_lambda).indexOf(true)];
};
用法:
[1,3,4,5,8,3,5].find(function(item) { return item % 2 == 0 })
=> 4
在 coffeescript 中也是如此:
Array.prototype.find = (search_lambda) -> @[@map(search_lambda).indexOf(true)]
评论
search_lambda
find
正如其他人所提到的,您可以使用 ,但它并非在所有浏览器中都可用。以下是 https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf 中的代码,以使其在旧浏览器中正常工作。Array.indexOf
indexOf 是 ECMA-262 标准的最新补充;因此,它可能 并非在所有浏览器中都存在。您可以通过插入 以下代码,允许使用 indexOf 在本身不支持它的实现中。这 算法正是 ECMA-262 第 5 版中指定的算法, 假设对象、类型错误、数字、数学楼层、数学.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;
}
}
我查看了提交的答案,发现它们仅适用于通过引用搜索对象的情况。带有参考对象比较的简单线性搜索。
但是,假设您没有对对象的引用,您将如何在数组中找到正确的对象?您将不得不对每个对象进行线性和深入的比较。想象一下,如果列表太大,并且其中的对象非常大,包含大块文本。性能会随着数组中元素的数量和大小而急剧下降。
你可以字符串化对象并将它们放在本机哈希表中,但这样你就会有数据冗余,记住这些键,因为 JavaScript 将它们保留为“for i in obj”,你只想检查对象是否存在,也就是说,你有键。
我考虑了一段时间来构建一个 JSON 模式验证器,我为本机哈希表设计了一个简单的包装器,类似于唯一的哈希表实现,但有一些优化异常,我将其留给本机哈希表来处理。它只需要性能基准测试...... 所有细节和代码都可以在我的博客上找到: http://stamat.wordpress.com/javascript-quickly-find-very-large-objects-in-a-large-array/ 我很快就会发布基准测试结果。
完整的解决方案是这样的:
var a = {'a':1,
'b':{'c':[1,2,[3,45],4,5],
'd':{'q':1, 'b':{'q':1, 'b':8},'c':4},
'u':'lol'},
'e':2};
var b = {'a':1,
'b':{'c':[2,3,[1]],
'd':{'q':3,'b':{'b':3}}},
'e':2};
var c = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
var hc = new HashCache([{a:3, b:2, c:5}, {a:15, b:2, c:'foo'}]); //init
hc.put({a:1, b:1});
hc.put({b:1, a:1});
hc.put(true);
hc.put('true');
hc.put(a);
hc.put(c);
hc.put(d);
console.log(hc.exists('true'));
console.log(hc.exists(a));
console.log(hc.exists(c));
console.log(hc.exists({b:1, a:1}));
hc.remove(a);
console.log(hc.exists(c));
用:
function isInArray(array, search)
{
return array.indexOf(search) >= 0;
}
// Usage
if(isInArray(my_array, "my_value"))
{
//...
}
评论
x ? true : false
通常是多余的。它就在这里。
array.indexOf(search) >= 0
已经是布尔值了。只。return array.indexOf(search) >= 0
用:
var myArray = ['yellow', 'orange', 'red'] ;
alert(!!~myArray.indexOf('red')); //true
要确切地知道此时的作用,请参阅这个问题波浪号在表达式之前做什么?。tilde
~
评论
ECMAScript 6 在 find 上有一个优雅的提议。
find 方法对每个元素执行一次回调函数 存在于数组中,直到它找到一个 callback 返回 true 的数组 价值。如果找到这样的元素,find 会立即返回值 该元素。否则,find 将返回 undefined。callback 是 仅对具有赋值的数组索引调用;它 对于已删除或从未删除的索引,不调用 被赋值。
这是关于这一点的 MDN 文档。
查找功能的工作方式如下。
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
您可以在 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;
}
});
}
评论
我使用以下内容:
Array.prototype.contains = function (v) {
return this.indexOf(v) > -1;
}
var a = [ 'foo', 'bar' ];
a.contains('foo'); // true
a.contains('fox'); // false
最热门的答案假设是原始类型,但如果你想找出一个数组是否包含一个具有某些特征的对象,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 月回答时,完全支持:caniuse.com 支持表Array.prototype.some()
评论
我们使用这个片段(适用于对象、数组、字符串):
/*
* @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
});
用法:
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
function contains(a, obj) {
return a.some(function(element){return element == obj;})
}
Array.prototype.some() 在第 5 版中被添加到 ECMA-262 标准中
评论
contains = (a, obj) => a.some((element) => element === obj))
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 的 不同,使用 SameValueZero 相等算法进行比较。这意味着您可以检测数组是否包含:indexOf
includes
NaN
[1, 2, NaN].includes(NaN); // true
与 不同的是,不会跳过缺失的索引:indexOf
includes
new Array(5).includes(undefined); // true
它可以被填充以使其在所有浏览器上运行。
单行:
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
希望更快的双向 indexOf
/ lastIndexOf
替代方案
2015
虽然新方法包含
非常好,但目前支持基本上为零。
很长一段时间以来,我一直在想一种方法来替换慢速/功能。indexOf
lastIndexOf
已经找到了一种高性能的方法,查看最佳答案。从中,我选择了 @Damir Zekic 发布的功能,这应该是最快的功能。但它也指出,基准是2008年的,因此已经过时。contains
我也更喜欢 ,但不是出于特定原因,我结束了使用 for 循环编写函数。也可以用 .while
for
while --
我很好奇,如果我在执行此操作时检查数组的两面,迭代速度是否会慢得多。显然不是,所以这个函数比投票最多的函数快两倍左右。显然,它也比原生的更快。这是在现实世界的环境中,您永远不知道您正在搜索的值是在数组的开头还是结尾。
当您知道您刚刚推送了一个带有值的数组时,使用 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');
性能测试
作为测试,我创建了一个包含 100k 个条目的数组。
三个查询:数组的开头、中间和结尾。
我希望你也觉得这很有趣,并测试性能。
注意:正如你所看到的,我稍微修改了函数以反映&输出(所以基本上用和)。这不应该伤害它。contains
indexOf
lastIndexOf
true
index
false
-1
阵列原型变体
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');
该函数也可以很容易地修改为返回 true 或 false,甚至是对象、字符串或其他任何内容。
这是变体: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');
这怎么可能?
我认为在数组中获取反射索引的简单计算非常简单,比进行实际循环迭代快两倍。
这是一个复杂的示例,每次迭代执行三次检查,但这只有在较长的计算中才有可能,这会导致代码速度变慢。
https://web.archive.org/web/20151019160219/http://jsperf.com/bidirectionalindexof/2
使用 lodash 的 some 函数。
它简洁、准确,并具有出色的跨平台支持。
接受的答案甚至不符合要求。
要求:推荐最简洁、最有效的方法来确定 JavaScript 数组是否包含对象。
采纳的答案:
$.inArray({'b': 2}, [{'a': 1}, {'b': 2}])
> -1
我的建议:
_.some([{'a': 1}, {'b': 2}], {'b': 2})
> true
笔记:
$.inArray 可以很好地确定标量数组中是否存在标量值......
$.inArray(2, [1,2])
> 1
...但是这个问题显然要求一种有效的方法来确定一个对象是否包含在数组中。
为了同时处理标量和对象,您可以这样做:
(_.isObject(item)) ? _.some(ary, item) : (_.indexOf(ary, item) > -1)
可以使用具有方法“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'));
评论
return proxy.has(obj)
function contains(arr, obj) { return new Set(arr).has(obj); }
这绝不是最好的,但我只是发挥了创造力并增加了曲目。
请勿使用此项
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'));
评论
您也可以使用此技巧:
var arrayContains = function(object) {
return (serverList.filter(function(currentObject) {
if (currentObject === object) {
return currentObject
}
else {
return false;
}
}).length > 0) ? true : false
}
评论
适用于所有现代浏览器的解决方案:
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);
}
用法:
contains([{a: 1}, {a: 2}], {a: 1}); // true
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;
};
}
用法:
contains([{a: 1}, {a: 2}], {a: 1}); // true
为什么使用?JSON.stringify
Array.indexOf
并且(以及这里的大多数答案)仅通过参考而不是价值进行比较。Array.includes
[{a: 1}, {a: 2}].includes({a: 1});
// false, because {a: 1} is a new object
奖金
未优化的 ES6 单线:
[{a: 1}, {a: 2}].some(item => JSON.stringify(item) === JSON.stringify({a: 1));
// true
注意: 如果键的顺序相同,则按值比较对象会更好,因此为了安全起见,您可以先使用如下包对键进行排序: https://www.npmjs.com/package/sort-keys
通过性能优化更新了函数。感谢itance指出这一点。contains
或者这个解决方案:
Array.prototype.includes = function (object) {
return !!+~this.indexOf(object);
};
评论
includes
好的,你可以优化你的代码来获得结果!
有很多方法可以做到这一点,这些方法更干净、更好,但我只是想获得您的模式并应用于该模式,只需在您的情况下简单地做这样的事情:JSON.stringify
function contains(a, obj) {
for (var i = 0; i < a.length; i++) {
if (JSON.stringify(a[i]) === JSON.stringify(obj)) {
return true;
}
}
return false;
}
评论
contains([{ a: 1, b: 2 }], { b: 2, a: 1 })
使用 idnexOf() 是一个很好的解决方案,但您应该隐藏嵌入式实现 indexOf() 函数,该函数返回带有 ~ 运算符的 -1:
function include(arr,obj) {
return !!(~arr.indexOf(obj));
}
- 要么使用 .
Array.indexOf(Object)
- 在 ECMA 7 中,可以使用 .
Array.includes(Object)
使用 ECMA 6,您可以使用用户的位置 定义的函数来搜索数组中的对象。
Array.find(FunctionName)
FunctionName
希望这有帮助!
我正在做一个项目,我需要像 python 这样的功能来删除所有重复值并返回一个新列表,所以我写了这个函数可能对某人有用set
function set(arr) {
var res = [];
for (var i = 0; i < arr.length; i++) {
if (res.indexOf(arr[i]) === -1) {
res.push(arr[i]);
}
}
return res;
}
它有一个参数:对象数组。数组中的每个对象都有两个整数属性,分别用 x 和 y 表示。该函数必须返回数组中满足numbers.x == numbers.y
var numbers = [ { x: 1, y: 1 },
{ x: 2, y: 3 },
{ x: 3, y: 3 },
{ x: 3, y: 4 },
{ x: 4, y: 5 } ];
var count = 0;
var n = numbers.length;
for (var i =0;i<n;i++)
{
if(numbers[i].x==numbers[i].y)
{count+=1;}
}
alert(count);
评论
for (var i = 0; i < n; i++) { if (numbers[i].x == (numbers[i] + 1).x) { count += 1; } }
如果您使用的是 ES6,您可以使用一组:
function arrayHas( array, element ) {
const s = new Set(array);
return s.has(element)
}
这应该比任何其他方法都性能更高
评论
indexOf
Array#includes
Array#indexOf
我建议使用下划线库,因为它返回值并且支持所有浏览器。
var findValue = _.find(array, function(item) {
return item.id == obj.id;
});
简单的解决方案:ES6 Features “includes” 方法
let arr = [1, 2, 3, 2, 3, 2, 3, 4];
arr.includes(2) // true
arr.includes(93) // false
除了其他人所说的之外,如果你没有要在数组中搜索的对象的引用,那么你可以做这样的事情。
let array = [1, 2, 3, 4, {"key": "value"}];
array.some((element) => JSON.stringify(element) === JSON.stringify({"key": "value"})) // true
array.some((element) => JSON.stringify(element) === JSON.stringify({})) // true
如果任何元素与给定条件匹配,则返回 true,如果没有任何元素与给定条件匹配,则返回 false。
评论
contains([{ a: 1, b: 2 }], { b: 2, a: 1 })
function countArray(originalArray) {
var compressed = [];
// make a copy of the input array
var copyArray = originalArray.slice(0);
// first loop goes over every element
for (var i = 0; i < originalArray.length; i++) {
var count = 0;
// loop over every element in the copy and see if it's the same
for (var w = 0; w < copyArray.length; w++) {
if (originalArray[i] == copyArray[w]) {
// increase amount of times duplicate is found
count++;
// sets item to undefined
delete copyArray[w];
}
}
if (count > 0) {
var a = new Object();
a.value = originalArray[i];
a.count = count;
compressed.push(a);
}
}
return compressed;
};
// It should go something like this:
var testArray = new Array("dog", "dog", "cat", "buffalo", "wolf", "cat", "tiger", "cat");
var newArray = countArray(testArray);
console.log(newArray);
令人惊讶的是,这个问题仍然没有添加最新的语法,增加了我的 2 美分。
假设我们有 Objects arrObj 数组,我们想在其中搜索 obj。
Array.prototype 中。indexOf ->(返回索引或 -1)通常用于查找数组中元素的索引。 这也可用于搜索对象,但仅在传递对同一对象的引用时才有效。
let obj = { name: 'Sumer', age: 36 };
let arrObj = [obj, { name: 'Kishor', age: 46 }, { name: 'Rupen', age: 26 }];
console.log(arrObj.indexOf(obj));// 0
console.log(arrObj.indexOf({ name: 'Sumer', age: 36 })); //-1
console.log([1, 3, 5, 2].indexOf(2)); //3
Array.prototype 中。包括 ->(返回 true 或 false)
console.log(arrObj.includes(obj)); //true
console.log(arrObj.includes({ name: 'Sumer', age: 36 })); //false
console.log([1, 3, 5, 2].includes(2)); //true
Array.prototype 中。find ->(接受回调,返回 CB 中返回 true 的第一个值/对象)。
console.log(arrObj.find(e => e.age > 40)); //{ name: 'Kishor', age: 46 }
console.log(arrObj.find(e => e.age > 40)); //{ name: 'Kishor', age: 46 }
console.log([1, 3, 5, 2].find(e => e > 2)); //3
Array.prototype 中。findIndex -> (接受回调,返回 CB 中返回 true 的第一个值/对象的索引)。
console.log(arrObj.findIndex(e => e.age > 40)); //1
console.log(arrObj.findIndex(e => e.age > 40)); //1
console.log([1, 3, 5, 2].findIndex(e => e > 2)); //1
由于 find 和 findIndex 接受回调,我们可以通过创造性地设置真实条件从数组中获取任何对象(即使我们没有引用)。
针对此要求的简单解决方案是使用find()
如果你有如下对象数组,
var users = [{id: "101", name: "Choose one..."},
{id: "102", name: "shilpa"},
{id: "103", name: "anita"},
{id: "104", name: "admin"},
{id: "105", name: "user"}];
然后,您可以检查具有您的值的对象是否已经存在:
let data = users.find(object => object['id'] === '104');
如果 data 为 null,则没有 admin,否则它将返回现有对象,如下所示:
{id: "104", name: "admin"}
然后,您可以在数组中找到该对象的索引,并使用以下代码替换该对象:
let indexToUpdate = users.indexOf(data);
let newObject = {id: "104", name: "customer"};
users[indexToUpdate] = newObject;//your new object
console.log(users);
您将获得如下值:
[{id: "101", name: "Choose one..."},
{id: "102", name: "shilpa"},
{id: "103", name: "anita"},
{id: "104", name: "customer"},
{id: "105", name: "user"}];
性能
今天 2020.01.07 我在 Chrome v78.0.0、Safari v13.0.4 和 Firefox v71.0.0 上的 MacOs HighSierra 10.13.6 上对 15 种选定的解决方案进行了测试。结论
- 基于 和 令人惊讶的是 (K,N,O) 的解决方案在所有浏览器上都是最慢的
JSON
Set
find
- es6 (F) 仅在 chrome 上速度很快
includes
- 基于 (C,D) 和 (G,H) 的解决方案在小型和大型数组上的所有浏览器上都非常快,因此它们可能是高效解决方案的最佳选择
for
indexOf
- 在循环期间索引减少的解决方案,(B) 较慢,可能是因为 CPU 缓存的方式工作。
- 当搜索的元素位于数组长度的 66% 的位置时,我还对大数组运行测试,并且基于 (C,D,E) 的解决方案给出了类似的结果(~630 ops/sec - 但 safari 和 firefox 上的 E 比 C 和 D 慢 10-20%)
for
结果
详
我执行 2 个测试用例:具有 10 个元素的数组和具有 1 个 milion 元素的数组。在这两种情况下,我们都把搜索到的元素放在数组中间。
let log = (name,f) => console.log(`${name}: 3-${f(arr,'s10')} 's7'-${f(arr,'s7')} 6-${f(arr,6)} 's3'-${f(arr,'s3')}`)
let arr = [1,2,3,4,5,'s6','s7','s8','s9','s10'];
//arr = new Array(1000000).fill(123); arr[500000]=7;
function A(a, val) {
var i = -1;
var n = a.length;
while (i++<n) {
if (a[i] === val) {
return true;
}
}
return false;
}
function B(a, val) {
var i = a.length;
while (i--) {
if (a[i] === val) {
return true;
}
}
return false;
}
function C(a, val) {
for (var i = 0; i < a.length; i++) {
if (a[i] === val) return true;
}
return false;
}
function D(a,val)
{
var len = a.length;
for(var i = 0 ; i < len;i++)
{
if(a[i] === val) return true;
}
return false;
}
function E(a, val){
var n = a.length-1;
var t = n/2;
for (var i = 0; i <= t; i++) {
if (a[i] === val || a[n-i] === val) return true;
}
return false;
}
function F(a,val) {
return a.includes(val);
}
function G(a,val) {
return a.indexOf(val)>=0;
}
function H(a,val) {
return !!~a.indexOf(val);
}
function I(a, val) {
return a.findIndex(x=> x==val)>=0;
}
function J(a,val) {
return a.some(x=> x===val);
}
function K(a, val) {
const s = JSON.stringify(val);
return a.some(x => JSON.stringify(x) === s);
}
function L(a,val) {
return !a.every(x=> x!==val);
}
function M(a, val) {
return !!a.find(x=> x==val);
}
function N(a,val) {
return a.filter(x=>x===val).length > 0;
}
function O(a, val) {
return new Set(a).has(val);
}
log('A',A);
log('B',B);
log('C',C);
log('D',D);
log('E',E);
log('F',F);
log('G',G);
log('H',H);
log('I',I);
log('J',J);
log('K',K);
log('L',L);
log('M',M);
log('N',N);
log('O',O);
This shippet only presents functions used in performance tests - it not perform tests itself!
小数组 - 10 个元素
您可以在您的机器中执行测试 这里
数组大 - 1.000.000 个元素
您可以在您的机器中执行测试 这里
Object.keys
用于获取对象的所有属性名称,并筛选与指定字符串完全匹配或部分匹配的所有值。
function filterByValue(array, string) {
return array.filter(o =>
Object.keys(o).some(k => o[k].toLowerCase().includes(string.toLowerCase())));
}
const arrayOfObject = [{
name: 'Paul',
country: 'Canada',
}, {
name: 'Lea',
country: 'Italy',
}, {
name: 'John',
country: 'Italy'
}];
console.log(filterByValue(arrayOfObject, 'lea')); // [{name: 'Lea', country: 'Italy'}]
console.log(filterByValue(arrayOfObject, 'ita')); // [{name: 'Lea', country: 'Italy'}, {name: 'John', country: 'Italy'}]
您还可以按特定键进行筛选,例如。
Object.keys(o).some(k => o.country.toLowerCase().includes(string.toLowerCase())));
现在,您只需在过滤后检查数组计数以检查值是否包含。
希望对您有所帮助。
将唯一项目添加到另一个列表
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
})
};
评论
使用 indexOf()
您可以使用 indexOf() 方法来检查数组中是否存在给定的值或元素。indexOf() 方法如果找到,则返回数组中元素的索引,如果未找到,则返回 -1。让我们看一下下面的例子:
var fruits = ["Apple", "Banana", "Mango", "Orange", "Papaya"];
var a = "Mango";
checkArray(a, fruits);
function checkArray(a, fruits) {
// Check if a value exists in the fruits array
if (fruits.indexOf(a) !== -1) {
return document.write("true");
} else {
return document.write("false");
}
}
使用 include() 方法
ES6 引入了 includes() 方法来非常轻松地执行此任务。但是,此方法仅返回 true 或 false,而不是索引号:
var fruits = ["Apple", "Banana", "Mango", "Orange", "Papaya"];
alert(fruits.includes("Banana")); // Outputs: true
alert(fruits.includes("Coconut")); // Outputs: false
alert(fruits.includes("Orange")); // Outputs: true
alert(fruits.includes("Cherry")); // Outputs: false
如需进一步参考,请在此处查看
这可能是一个详细而简单的解决方案。
//plain array
var arr = ['a', 'b', 'c'];
var check = arr.includes('a');
console.log(check); //returns true
if (check)
{
// value exists in array
//write some codes
}
// array with objects
var arr = [
{x:'a', y:'b'},
{x:'p', y:'q'}
];
// if you want to check if x:'p' exists in arr
var check = arr.filter(function (elm){
if (elm.x == 'p')
{
return elm; // returns length = 1 (object exists in array)
}
});
// or y:'q' exists in arr
var check = arr.filter(function (elm){
if (elm.y == 'q')
{
return elm; // returns length = 1 (object exists in array)
}
});
// if you want to check, if the entire object {x:'p', y:'q'} exists in arr
var check = arr.filter(function (elm){
if (elm.x == 'p' && elm.y == 'q')
{
return elm; // returns length = 1 (object exists in array)
}
});
// in all cases
console.log(check.length); // returns 1
if (check.length > 0)
{
// returns true
// object exists in array
//write some codes
}
例如:Array.prototype.includes
const fruits = ['coconut', 'banana', 'apple']
const doesFruitsHaveCoconut = fruits.includes('coconut')// true
console.log(doesFruitsHaveCoconut)
也许从 MDN 阅读此文档: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes
您可以使用 findIndex 函数来检查数组是否具有特定值。
arrObj.findIndex(obj => obj === comparedValue) !== -1;
如果 arrObj 包含 comparedValue,则返回 true,否则返回 false。
使用正则表达式:
console.log(new RegExp('26242').test(['23525', '26242', '25272'].join(''))) // true
检查数组 JavaScript 中是否存在值的最佳默认方法是some()
Array.prototype.some()
该方法测试数组中是否至少有一个元素通过了所提供函数实现的测试。如果在数组中找到所提供函数返回 true 的元素,则返回 true;否则返回 false。它不会修改数组。some()
const array = [1, 2, 3, 4, 5];
// checks whether an element is even
const even = (element) => element % 2 === 0;
console.log(array.some(even));
// expected output: true
更多文档 Array.prototype.some() - JavaScript |MDN网络
您也可以使用其他两种方法是 和 。使用这些方法,您可以获得结果,但不是最好的结果。find()
includes()
Array.prototype.find() - JavaScript |MDN网络
Array.prototype.includes() - JavaScript |MDN网络
有几种方法可以很容易地实现(、、、includes
some
find
findIndex
)
const array = [1, 2, 3, 4, 5, 6, 7];
console.log(array.includes(3));
//includes() determines whether an array includes a certain value among its entries
console.log(array.some(x => x === 3));
//some() tests if at least one element in the array passes the test implemented by the provided function
console.log(array.find(x => x === 3) ? true : false);
//find() returns the value of the first element in the provided array that satisfies the provided testing function
console.log(array.findIndex(x => x === 3) > -1);
//findIndex() returns the index of the first element in the array that satisfies the provided testing function, else returning -1.
更多关于 includes, some, find, findIndex
如果您只是想检查一个值是否包含在集合中,那么使用 、 可以有重复的值而不能有重复值会更合适。此外,替换为将性能从 O(n2) 提高到 O(n)。当您必须为同一 Set 查找多个值时,这将非常有用。因此,如果您只查找单个值,则使用没有任何好处,则可以只使用 .Set
Arrays
Sets
array.includes
set.has
set.has
array.includes
创建了一个 jsbench demo,你可以运行它来检查性能。
测试执行截图:
评论
在 Javascript 中查找数组是否包含值的最快方法是:
function existsInArrayForIgnoreDataType(arr, targetElem) {
for (let i = 0; i < arr.length; i++) {
if (arr[i] == targetElem) return true
}
return false
}
你可以在这里找到我所做的完整研究。
评论
includes
有几种方法可以找出答案。 您可以使用内置的 Array 方法。最突出的使用是数组查找方法。
const arr1 = [1, 2, 3, 4, 5]
const result = arr1.find(ele => ele === 4)
console.log(result) //4
const result2 = arr1.find(ele => ele === 6)
console.log(result2) //undefined
/*
If the element is present inside the array
then it will return the first element that
satisfies the given condition. Otherwise
undefined will return.
*/
如果你的数组是排序的,那么你可以对数组使用二进制搜索。
const recursiveBinarySearch = (arr, target, first = 0, last = arr.length - 1) => {
let firstIndex = first;
let lastIndex = last;
if (lastIndex < firstIndex) return -1;
const midIndex = Math.floor((firstIndex + lastIndex) / 2);
if (arr[midIndex] === target) return midIndex;
if (arr[midIndex] < target) return recursiveBinarySearch(arr, target, midIndex + 1, last);
if (arr[midIndex] > target) return recursiveBinarySearch(arr, target, firstIndex, midIndex - 1);
};
console.log(recursiveBinarySearch([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10)); //9
console.log(recursiveBinarySearch([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 2)); // 1
console.log(recursiveBinarySearch(['bird', 'cat', 'dog', 'fish'], 'dog')); // 2
复杂度 O(n/2)
您可以使用任何库函数,但我使用核心 JavaScript 做到了。如果我们得到 return 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
评论
这就是你可以做到的。
const arr = [1, 2, 3, 4, 5];
console.log(arr.includes(3)); // true
console.log(arr.includes(6)); // false
查看很多结果
const array = [1, 2, 3, 4, 2]
console.log(
array.indexOf(2), // 1
array.filter(e => e == 2), // [ 2, 2 ]
array.includes(2), // true
array.find(e => e == 2) // 2
)
// view does not match
console.log(
array.indexOf(12), // -1
array.filter(e => e == 12), // []
array.includes(12), // false
array.find(e => e == 12) // undefined
)
// match
console.log(
array.indexOf(2) != -1, // true
array.filter(e => e == 2).length > 0, // true
array.includes(2), // true
array.find(e => e == 2) != undefined // true
)
上一个:如何访问数组/对象?
评论
~[1,2,3].indexOf(4)
~[1,2,3].indexOf(3)
~
不是您要用于转换为布尔值的内容,因为您需要.但是在这种情况下,您要用 -1 检查是否相等,否则函数可能以二进制结束,它将单独反转值的每个位。!
return [1,2,3].indexOf(3) === -1;
~
[1,2,3].indexOf(4)
~
-1
0
~
indexOf
[[1,2],[3,4]].includes([3,4])