查找项目是不是在 JavaScript 数组中的最佳方法? [复制]
Posted
技术标签:
【中文标题】查找项目是不是在 JavaScript 数组中的最佳方法? [复制]【英文标题】:Best way to find if an item is in a JavaScript array? [duplicate]查找项目是否在 JavaScript 数组中的最佳方法? [复制] 【发布时间】:2010-09-13 17:13:48 【问题描述】:判断一个对象是否在数组中的最好方法是什么?
这是我知道的最好的方法:
function include(arr, obj)
for (var i = 0; i < arr.length; i++)
if (arr[i] == obj) return true;
console.log(include([1, 2, 3, 4], 3)); // true
console.log(include([1, 2, 3, 4], 6)); // undefined
【问题讨论】:
见:***.com/a/25765186/1320932 两件事:1.) 对于一个不修改任何状态的函数来说,'include' 是一个非常糟糕的名字。对于只返回布尔值的函数来说尤其糟糕。 2.) 您需要添加“return(false);”在函数结束之前。 从 ECMAScript 2016 开始,您可以使用 Array.prototype.includes 函数:myArray.includes(3); // 是的 在 ES6 中,您可以执行类似 arr.find(lamda function) 的操作,例如:[1, 2, 3,4,5].find(x => x == 3)。如果找到元素,则返回否则返回未定义 arr.some(element => element === obj); some 是最好的方法,因为当它找到一个项目然后打破循环时。 【参考方案1】:从 ECMAScript 2016 开始,您可以使用 includes()
arr.includes(obj);
如果您想支持 IE 或其他旧版浏览器:
function include(arr,obj)
return (arr.indexOf(obj) != -1);
编辑: 不过,这不适用于 IE6、7 或 8。如果它不存在,最好的解决方法是自己定义它:
Mozilla's (ECMA-262) 版本:
if (!Array.prototype.indexOf)
Array.prototype.indexOf = function(searchElement /*, fromIndex */)
"use strict";
if (this === void 0 || 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 > 0)
n = Number(arguments[1]);
if (n !== n)
n = 0;
else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0))
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;
;
Daniel James的版本:
if (!Array.prototype.indexOf)
Array.prototype.indexOf = function (obj, fromIndex)
if (fromIndex == null)
fromIndex = 0;
else if (fromIndex < 0)
fromIndex = Math.max(0, this.length + fromIndex);
for (var i = fromIndex, j = this.length; i < j; i++)
if (this[i] === obj)
return i;
return -1;
;
roosteronacid的版本:
Array.prototype.hasObject = (
!Array.indexOf ? function (o)
var l = this.length + 1;
while (l -= 1)
if (this[l - 1] === o)
return true;
return false;
: function (o)
return (this.indexOf(o) !== -1);
);
【讨论】:
我很好奇为什么您的 Mozilla 功能版本与您链接的网站如此不同。是你自己修改的还是只是旧版本之类的? @Shenjoku:“2008 年 9 月 27 日 15:45 回答” 嗯,这就是我的答案哈哈。我不能仅通过查看 mozilla 网站来判断是否有旧版本,所以我不确定。不重要,只是好奇。无论如何,这仍然很有帮助,因此您会获得支持;) @Vinko Vrsalovic 是的,这是一个很好的解决方案,但是您应该隐藏嵌入式实现 indexOf() 函数,它使用 ~ 运算符返回 -1: function include(arr,obj) return !!(~ arr.indexOf(obj)) ; 但是,自从indexOf什么时候兼容IE,因为我发现它兼容IE w3schools.com/jsref/jsref_indexof.asp【参考方案2】:如果你使用的是 jQuery:
$.inArray(5 + 5, [ "8", "9", "10", 10 + "" ]);
欲了解更多信息:http://api.jquery.com/jQuery.inArray/
【讨论】:
请注意,“inArray”是用词不当,因为它不返回布尔值 - 它返回找到的第一个元素的索引。因此,如果您要检查元素是否存在,您应该使用if (-1 != $.inArray(...)) ...
。
有帮助,但我认为这不是一个合适的答案。在我看来,这个问题被标记为“javascript”,表示“香草”。 :)【参考方案3】:
首先,在 JavaScript 中为还没有 indexOf
的浏览器实现 indexOf
。例如,请参阅 Erik Arvidsson's array extras(也称为 associated blog post)。然后您可以使用indexOf
,而无需担心浏览器支持。这是他的indexOf
实现的略微优化版本:
if (!Array.prototype.indexOf)
Array.prototype.indexOf = function (obj, fromIndex)
if (fromIndex == null)
fromIndex = 0;
else if (fromIndex < 0)
fromIndex = Math.max(0, this.length + fromIndex);
for (var i = fromIndex, j = this.length; i < j; i++)
if (this[i] === obj)
return i;
return -1;
;
它已更改为存储长度,因此不需要每次迭代都查找它。但差别不是很大。不太通用的函数可能会更快:
var include = Array.prototype.indexOf ?
function(arr, obj) return arr.indexOf(obj) !== -1; :
function(arr, obj)
for(var i = -1, j = arr.length; ++i < j;)
if(arr[i] === obj) return true;
return false;
;
我更喜欢使用标准功能,并在真正需要时保留这种微优化。但是,如果您热衷于微优化,我将与 cmets 中的公鸡酮酸相关的 benchmarks 改编为 benchmark searching in arrays。虽然它们非常粗略,但完整的调查将测试具有不同类型、不同长度的数组并找到出现在不同位置的对象。
【讨论】:
您链接到的代码示例在大型数组上运行缓慢。请参阅我的 hasItem() 函数实现示例中的 cmets。 看看这些基准测试:blogs.sun.com/greimer/resource/loop-test.htm For 循环很慢。但我猜基准测试中使用的数组非常庞大:) blogs.sun.com/greimer/resource/loop-test.html 我同意。我也很务实。但在优化语言基础的情况下,我认为实现功能尽可能提高性能是很好的设计。 使用 mozilla Array.indexOf polyfill:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…【参考方案4】:如果数组未排序,实际上没有更好的方法(除了使用上面提到的 indexOf,我认为这相当于同一件事)。如果数组已排序,则可以进行二进制搜索,其工作原理如下:
-
选择数组的中间元素。
您要查找的元素是否比您选择的元素大?如果是这样,您已经消除了数组的下半部分。如果不是,您已经淘汰了上半部分。
选择数组剩余一半的中间元素,并按照步骤 2 继续,消除剩余数组的一半。最终,您要么找到您的元素,要么没有剩余的数组可供查看。
二分查找的运行时间与数组长度的对数成正比,因此它比查看每个单独的元素要快得多。
【讨论】:
您可能应该提到,这种方法在大型排序数组上比小型数组更快。 为什么在较小的阵列上会变慢? @vidstige:他的意思是它可以很好地扩展,但对于小输入来说不一定是最快的。 这在 O(lg n) 中运行,而不是 O(n),后者更具可扩展性【参考方案5】:[ ].has(obj)
假设.indexOf()
已实现
Object.defineProperty( Array.prototype,'has',
value:function(o, flag)
if (flag === undefined)
return this.indexOf(o) !== -1;
else // only for raw js object
for(var v in this)
if( JSON.stringify(this[v]) === JSON.stringify(o)) return true;
return false;
,
// writable:false,
// enumerable:false
)
!!!不要创建Array.prototype.has=function()...
,因为你会在每个数组中添加一个可枚举的元素,而 js 会被破坏。
//use like
[22 ,'a', prop:'x'].has(12) // false
["a","b"].has("a") // true
[1,a:1].has(a:1,1) // true
[1,a:1].has(a:1) // false
使用第二个参数(标志)强制按值而不是参考进行比较
比较原始对象
[o1].has(o2,true) // true if every level value is same
【讨论】:
【参考方案6】:这取决于你的目的。如果您为 Web 编程,请避免使用 indexOf
,Internet Explorer 6 不支持它(其中很多仍在使用!),或者有条件地使用:
if (yourArray.indexOf !== undefined) result = yourArray.indexOf(target);
else result = customSlowerSearch(yourArray, target);
indexOf
可能是用本机代码编码的,所以它比你在 JavaScript 中可以做的任何事情都要快(如果数组合适,二进制搜索/二分法除外)。
注意:这是一个品味问题,但我会在你的例程结束时做一个return false;
,以返回一个真正的布尔值......
【讨论】:
哈哈...我觉得现在还有一个 IE6 客户端... 不应该在***页面中出现“截至 2008 年”,这样人们就知道这个声明肯定已经过时了 @allan.simon 查看答案底部的图标(和统计信息)。就在上面,有“2008 年 9 月 27 日 16:28 回答”。它被称为日期,习惯于 Stack Overflow 的人们会在查看这些日期时持怀疑态度...也就是说,我当地的公共图书馆仍然在他们的计算机上安装了 IE6! (但幸运的是,有人安装了 Chrome!)【参考方案7】:这里有一些元知识 - 如果你想知道可以用数组做什么,请查看文档 - 这是 Mozilla 的数组页面
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array
您会在此处看到对 indexOf 的引用,它是在 Javascript 1.6 中添加的
【讨论】:
包含有关 Javascript 1.8 及更高版本信息的手册的奇怪 URL! :) 这不包括作者询问的对象数组 @VinkoVrsalovic:网址已更改为developer.mozilla.org/en-US/docs/JavaScript/Reference/…【参考方案8】:这里详细介绍了一种检查对象是否为 javascript 中的数组的可靠方法:
这里有两个来自xa.js 框架的函数,我将它们附加到utils =
“容器”。这些应该可以帮助您正确检测数组。
var utils = ;
/**
* utils.isArray
*
* Best guess if object is an array.
*/
utils.isArray = function(obj)
// do an instanceof check first
if (obj instanceof Array)
return true;
// then check for obvious falses
if (typeof obj !== 'object')
return false;
if (utils.type(obj) === 'array')
return true;
return false;
;
/**
* utils.type
*
* Attempt to ascertain actual object type.
*/
utils.type = function(obj)
if (obj === null || typeof obj === 'undefined')
return String (obj);
return Object.prototype.toString.call(obj)
.replace(/\[object ([a-zA-Z]+)\]/, '$1').toLowerCase();
;
如果你想检查一个对象是否在一个数组中,我也会包含这个代码:
/**
* Adding hasOwnProperty method if needed.
*/
if (typeof Object.prototype.hasOwnProperty !== 'function')
Object.prototype.hasOwnProperty = function (prop)
var type = utils.type(this);
type = type.charAt(0).toUpperCase() + type.substr(1);
return this[prop] !== undefined
&& this[prop] !== window[type].prototype[prop];
;
最后是这个 in_array 函数:
function in_array (needle, haystack, strict)
var key;
if (strict)
for (key in haystack)
if (!haystack.hasOwnProperty[key]) continue;
if (haystack[key] === needle)
return true;
else
for (key in haystack)
if (!haystack.hasOwnProperty[key]) continue;
if (haystack[key] == needle)
return true;
return false;
【讨论】:
虽然这在理论上可以回答这个问题,it would be preferable 在此处包含答案的基本部分,并提供链接以供参考。此外,当您一次复制/粘贴相同的仅链接回答几个非常老的问题时,它看起来就像垃圾邮件。 对不起比尔,我真的不是故意让它看起来像垃圾邮件,我只是想更新一些关于这个话题的老问题。我在这里编辑了帖子以包含实际答案,而不是链接。 @Bill,实际上重新阅读了这个问题,这甚至根本没有回答。我一定是搞错了。以上是关于查找项目是不是在 JavaScript 数组中的最佳方法? [复制]的主要内容,如果未能解决你的问题,请参考以下文章