在 JavaScript 中如何检查数组是否包含值?

发布于 2024-07-08 10:18:49 字数 491 浏览 5 评论 0 原文

找出 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 在数组中查找对象的问题。

What is the most concise and efficient way to find out if a JavaScript array contains a value?

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(30

烟花肆意 2024-07-15 10:18:49

现代浏览器有 Array#includes ,它完全做到了这一点,并且受到除 IE 之外的所有人的广泛支持

console.log(['joe', 'jane', 'mary'].includes('jane')); // true

您还可以使用 Array#indexOf< /code>,不太直接,但不需要针对过时的浏览器进行填充。

console.log(['joe', 'jane', 'mary'].indexOf('jane') >= 0); // true


许多框架也提供类似的方法:

请注意,某些框架将其实现为函数,而其他框架则添加了函数到数组原型。

Modern browsers have Array#includes, which does exactly that and is widely supported by everyone except IE:

console.log(['joe', 'jane', 'mary'].includes('jane')); // true

You can also use Array#indexOf, which is less direct, but doesn't require polyfills for outdated browsers.

console.log(['joe', 'jane', 'mary'].indexOf('jane') >= 0); // true


Many frameworks also offer similar methods:

Notice that some frameworks implement this as a function, while others add the function to the array prototype.

深府石板幽径 2024-07-15 10:18:49

2019 年更新:这个答案来自 2008 年(11 岁了!),与现代 JS 的使用无关。 承诺的性能改进是基于当时浏览器中完成的基准测试。 它可能与现代 JS 执行上下文无关。 如果您需要简单的解决方案,请寻找其他答案。 如果您需要最佳性能,请在相关执行环境中对自己进行基准测试。

正如其他人所说,通过数组进行迭代可能是最好的方法,但它 已被证明,递减的 while 循环是JavaScript 中迭代的最快方法。 所以你可能想重写你的代码如下:

function contains(a, obj) {
    var i = a.length;
    while (i--) {
       if (a[i] === obj) {
           return true;
       }
    }
    return false;
}

当然,你也可以扩展 Array 原型:

Array.prototype.contains = function(obj) {
    var i = this.length;
    while (i--) {
        if (this[i] === obj) {
            return true;
        }
    }
    return false;
}

现在你可以简单地使用以下内容:

alert([1, 2, 3].contains(2)); // => true
alert([1, 2, 3].contains('2')); // => false

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:

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
水水月牙 2024-07-15 10:18:49

最上面的答案假设原始类型,但如果您想查明数组是否包含具有某些特征的对象Array.prototype.some() 是一个优雅的解决方案:

const items = [ {a: '1'}, {a: '2'}, {a: '3'} ]

items.some(item => item.a === '3')  // returns true
items.some(item => item.a === '4')  // returns false

它的好处是一旦找到元素,迭代就会中止,因此避免了不必要的迭代周期。

此外,它非常适合 if 语句,因为它返回一个布尔值:

if (items.some(item => item.a === '3')) {
  // do something
}

* 正如 jamess 在评论中指出的那样,在 2018 年 9 月发表此答案时, Array.prototype.some( ) 完全支持:caniuse.com 支持表

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:

const items = [ {a: '1'}, {a: '2'}, {a: '3'} ]

items.some(item => item.a === '3')  // returns true
items.some(item => item.a === '4')  // returns false

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:

if (items.some(item => item.a === '3')) {
  // do something
}

* As jamess pointed out in the comment, at the time of this answer, September 2018, Array.prototype.some() is fully supported: caniuse.com support table

清风不识月 2024-07-15 10:18:49

indexOf 也许,但它是“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(以及其他不支持 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:

[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).

一城柳絮吹成雪 2024-07-15 10:18:49

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

indexOf 不同,它使用 严格相等比较包含使用SameValueZero 相等算法。 这意味着您可以检测数组是否包含 NaN

[1, 2, NaN].includes(NaN); // true

indexOf 不同的是,includes 不会跳过缺失的索引:

new Array(5).includes(undefined); // true

它可以是 polyfilled 使其适用于所有浏览器。

ECMAScript 7 introduces 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:

[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:

[1, 2, NaN].includes(NaN); // true

Also unlike indexOf, includes does not skip missing indices:

new Array(5).includes(undefined); // true

It can be polyfilled to make it work on all browsers.

勿忘初心 2024-07-15 10:18:49

假设您已经像这样定义了一个数组:

const array = [1, 2, 3, 4]

下面是检查其中是否有 3 的三种方法。 它们都返回 truefalse

原生数组方法(自 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

Let's say you've defined an array like so:

const array = [1, 2, 3, 4]

Below are three ways of checking whether there is a 3 in there. All of them return either true or false.

Native Array method (since ES2016) (compatibility table)

array.includes(3) // true

As custom Array method (pre 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

Simple function

const includes = (a, v) => a.indexOf(v) !== -1
includes(array, 3) // true
笛声青案梦长安 2024-07-15 10:18:49

这是 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;
        };
}

Here's a JavaScript 1.6 compatible implementation of 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;
        };
}
偏爱你一生 2024-07-15 10:18:49

使用:

function isInArray(array, search)
{
    return array.indexOf(search) >= 0;
}

// Usage
if(isInArray(my_array, "my_value"))
{
    //...
}

Use:

function isInArray(array, search)
{
    return array.indexOf(search) >= 0;
}

// Usage
if(isInArray(my_array, "my_value"))
{
    //...
}
人│生佛魔见 2024-07-15 10:18:49

扩展 JavaScript Array 对象是一个非常糟糕的主意,因为您将新属性(您的自定义方法)引入到 for-in 循环中,这可能会破坏现有脚本。 几年前,Prototype 库的作者必须重新设计他们的库实现,以删除仅这种事。

如果您不需要担心与页面上运行的其他 JavaScript 的兼容性,请使用它,否则,我会推荐更尴尬但更安全的独立函数解决方案。

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.

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.

友谊不毕业 2024-07-15 10:18:49

今天的性能

2020.01.07 我在 Chrome v78.0.0、Safari v13.0.4 和 Firefox v71.0.0 上的 MacOs HighSierra 10.13.6 上对 15 个选定的解决方案进行了测试。 慢

  • 结论 基于 JSONSet 和令人惊讶的 find (K,N,O) 的解决方案在 es6 包含<的所有浏览器上是最
  • 的/code> (F) 仅在 chrome 上速度很快,
  • 基于 for (C,D) 和 indexOf (G,H) 的解决方案在所有浏览器上都相当快小数组和大数组,因此它们可能是有效解决方案的最佳选择,
  • 循环期间索引减少的解决方案,(B) 速度较慢,可能是因为 CPU 缓存工作
  • 当搜索的元素位于数组长度的 66% 位置时,我还对大数组运行测试,并且基于 for (C,D,E) 的解决方案给出了类似的结果(~630 操作/秒 - 但E 在 safari 和 firefox 上比 C 和 D 慢 10-20%)

结果

在此处输入图像描述

详细信息

我执行 2 个测试用例:对于具有 10 个元素的数组,以及具有 100 万个元素的数组。 在这两种情况下,我们都将搜索到的元素放在数组中间。

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 个元素

您可以此处

输入图片此处描述

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

  • solutions based on JSON, Set and surprisingly find (K,N,O) are slowest on all browsers
  • the es6 includes (F) is fast only on chrome
  • the solutions based on for (C,D) and indexOf (G,H) are quite-fast on all browsers on small and big arrays so probably they are best choice for efficient solution
  • the solutions where index decrease during loop, (B) is slower probably because the way of CPU cache works.
  • I also run test for big array when searched element was on position 66% of array length, and solutions based on for (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

enter image description here

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.

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!

Array small - 10 elements

You can perform tests in your machine HERE

enter image description here

Array big - 1.000.000 elements

You can perform tests in your machine HERE

enter image description here

初熏 2024-07-15 10:18:49

单线:

function contains(arr, x) {
    return arr.filter(function(elem) { return elem == x }).length > 0;
}

One-liner:

function contains(arr, x) {
    return arr.filter(function(elem) { return elem == x }).length > 0;
}
乖乖公主 2024-07-15 10:18:49

跳出框框思考一下,如果您多次进行此调用,那么使用关联数组 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 array a Map to do lookups using a hash function.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map

芯好空 2024-07-15 10:18:49

我使用以下内容:

Array.prototype.contains = function (v) {
    return this.indexOf(v) > -1;
}

var a = [ 'foo', 'bar' ];

a.contains('foo'); // true
a.contains('fox'); // false

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
哎呦我呸! 2024-07-15 10:18:49
function contains(a, obj) {
    return a.some(function(element){return element == obj;})
}

Array.prototype.some() 已添加到 ECMA第五版-262标准

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

何以笙箫默 2024-07-15 10:18:49

有几种方法可以轻松实现(includessomefindfindIndex

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.

有关包含的更多信息,一些查找findIndex

There are a couple of methods which makes it easy to achieve (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.

More about includes, some, find, findIndex

望笑 2024-07-15 10:18:49

如果您使用的是 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.

慵挽 2024-07-15 10:18:49

希望更快的双向 indexOf / lastIndexOf 替代方案

2015

而新方法includes 非常好,目前支持基本为零。

很长一段时间以来,我一直在思考一种方法来取代缓慢的 indexOf/lastIndexOf 函数。

通过查看最热门的答案,已经找到了一种高性能的方法。 从这些中,我选择了 @Damir Zekic 发布的 contains 函数,它应该是最快的函数。 但它也指出,基准来自 2008 年,因此已经过时。

我也更喜欢 while 而不是 for,但由于没有特定原因,我最终用 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');

性能测试

https ://jsbench.me/7el1b8dj80

作为测试,我创建了一个包含 100k 条目的数组。

三个查询:开头、中间和第三个查询 在数组的末尾。

我希望您也觉得这很有趣并测试其性能。

注意:正如您所看到的,我稍微修改了 contains 函数以反映 indexOf & lastIndexOf 输出(所以基本上 true 带有 indexfalse 带有 -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/bidirectionindexof/2

A hopefully faster bidirectional indexOf / lastIndexOf alternative

2015

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 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 --.

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

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

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 the indexOf & lastIndexOf output (so basically true with the index and false with -1). That shouldn't harm it.

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.

And here is the while variant:

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.

https://web.archive.org/web/20151019160219/http://jsperf.com/bidirectionalindexof/2

椒妓 2024-07-15 10:18:49
function inArray(elem,array)
{
    var len = array.length;
    for(var i = 0 ; i < len;i++)
    {
        if(array[i] == elem){return i;}
    }
    return -1;
} 

如果找到则返回数组索引,如果未找到则返回-1

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

清浅ˋ旧时光 2024-07-15 10:18:49

如果您重复检查数组中是否存在对象,您可能应该

  1. 通过执行
  2. 将更新对象作为删除+排序插入操作并
  3. 使用二分搜索contains(a, obj) 中查找。

If you are checking repeatedly for existence of an object in an array you should maybe look into

  1. Keeping the array sorted at all times by doing insertion sort in your array (put new objects in on the right place)
  2. Make updating objects as remove+sorted insert operation and
  3. Use a binary search lookup in your contains(a, obj).
身边 2024-07-15 10:18:49

我们使用此代码片段(适用于对象、数组、字符串):

/*
 * @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

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
悲歌长辞 2024-07-15 10:18:49

适用于所有现代浏览器的解决方案:

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.indexOfArray.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


通过性能优化更新了 contains 函数。 感谢 itinance 指出这一点。

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:

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.

[{a: 1}, {a: 2}].includes({a: 1});
// false, because {a: 1} is a new object

Bonus

Non-optimized ES6 one-liner:

[{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


Updated the contains function with a perf optimization. Thanks itinance for pointing it out.

孤蝉 2024-07-15 10:18:49

使用 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)

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:

$.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(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)
浪漫人生路 2024-07-15 10:18:49

满足此要求的简单解决方案是使用 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');

如果数据为 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"}];

Simple solution for this requirement is using find()

If you're having array of objects like below,

var users = [{id: "101", name: "Choose one..."},
{id: "102", name: "shilpa"},
{id: "103", name: "anita"},
{id: "104", name: "admin"},
{id: "105", name: "user"}];

Then you can check whether the object with your value is already present or not:

let data = users.find(object => object['id'] === '104');

if data is null then no admin, else it will return the existing object like:

{id: "104", name: "admin"}

Then you can find the index of that object in the array and replace the object using the code:

let indexToUpdate = users.indexOf(data);
let newObject = {id: "104", name: "customer"};
users[indexToUpdate] = newObject;//your new object
console.log(users);

you will get value like:

[{id: "101", name: "Choose one..."},
{id: "102", name: "shilpa"},
{id: "103", name: "anita"},
{id: "104", name: "customer"},
{id: "105", name: "user"}];
执笏见 2024-07-15 10:18:49

ECMAScript 6 对 find 有一个优雅的建议。

find方法对每个元素执行一次回调函数
存在于数组中,直到找到回调返回 true 的数组
价值。 如果找到这样的元素,find 立即返回该值
该元素的。 否则,find 返回未定义。 回调是
仅针对已分配值的数组索引调用; 它
不会为已删除或从未删除的索引调用
已指定值。

这是关于该问题的 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

您可以通过 定义函数

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;
    }
  });
}

ECMAScript 6 has an elegant proposal on find.

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.

Here is the MDN documentation on that.

The find functionality works like this.

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.

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;
    }
  });
}
我也只是我 2024-07-15 10:18:49

虽然 array.indexOf(x)!=-1 是执行此操作的最简洁方法(并且非 Internet Explorer 浏览器已支持十多年......),但它并不是 O (1),而是 O(N),这很糟糕。 如果您的数组不会更改,您可以将数组转换为哈希表,然后执行 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 中分两行存储哈希表,但如果您选择稍后编辑数组,则这会产生错误的结果。你可以保持这种状态,这与 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 do table[x]!==undefined or ===undefined:

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.)

习惯成性 2024-07-15 10:18:49

可以使用具有方法“has( )”:

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'));

One can use Set that has the method "has()":

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'));

时光瘦了 2024-07-15 10:18:49

使用:

var myArray = ['yellow', 'orange', 'red'] ;

alert(!!~myArray.indexOf('red')); //true

Demo

要确切了解 波浪号 ~此时请参考这个问题 当波浪号出现在表达式之前时,它有什么作用?

Use:

var myArray = ['yellow', 'orange', 'red'] ;

alert(!!~myArray.indexOf('red')); //true

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?.

第七度阳光i 2024-07-15 10:18:49

好的,您只需优化您的代码即可获得结果!

有很多方法可以做到这一点,这些方法更干净、更好,但我只是想获取您的模式并使用 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;
}

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:

function contains(a, obj) {
    for (var i = 0; i < a.length; i++) {
        if (JSON.stringify(a[i]) === JSON.stringify(obj)) {
            return true;
        }
    }
    return false;
}
愿得七秒忆 2024-07-15 10:18:49

令人惊讶的是这个问题仍然没有添加最新的语法,添加我的 2 美分。

假设我们有对象数组 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.包含 -> (返回truefalse

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 需要回调,因此我们可以通过创造性地设置 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.

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.includes -> (returns true or 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 -> (takes callback, returns first value/object that returns true in CB).

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 -> (takes callback, returns index of first value/object that returns true in CB).

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

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.

甜扑 2024-07-15 10:18:49

它有一个参数:一组对象。 数组中的每个对象都有两个整数属性,用 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);

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

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);

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文