find一个项目是否在JavaScript数组中的最佳方法?
什么是最好的方式来find一个对象是否在一个数组?
这是我知道的最好的方法:
function include(arr, obj) { for(var i=0; i<arr.length; i++) { if (arr[i] == obj) return true; } } include([1,2,3,4], 3); // true include([1,2,3,4], 6); // undefined
function include(arr,obj) { return (arr.indexOf(obj) != -1); }
编辑:这将无法在IE6,7或8上工作。 最好的解决方法是自己定义它,如果它不存在:
-
Mozilla的 (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; }; }
-
丹尼尔·詹姆斯的版本:
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); } );
如果你正在使用jQuery:
$.inArray(5 + 5, [ "8", "9", "10", 10 + "" ]);
欲了解更多信息: http : //api.jquery.com/jQuery.inArray/
首先,对于尚未拥有它的浏览器,在JavaScript中实现indexOf
。 例如,请参阅Erik Arvidsson的数组extras (也是关联的博客文章 )。 然后你可以使用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; }; }
它改变了存储的长度,以便它不需要每次迭代查找它。 但差别并不大。 一个不太常用的function可能会更快:
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; };
我更喜欢使用标准函数,并在需要时留下这种微型优化。 但是,如果你热衷于微型优化,我将在评论中关联的基准进行了调整,以便在数组中进行基准search 。 他们是非常粗糙的,一个完整的调查将testing不同types,不同长度的数组,并find不同地方发生的对象。
如果这个数组是未sorting的,那么除了使用上面提到的indexOf(我认为它们是相同的)之外,还没有更好的方法。 如果数组已sorting,则可以执行二进制search,其工作方式如下所示:
- select数组的中间元素。
- 你所寻找的元素是否大于你select的元素? 如果是这样,你已经消除了数组的下半部分。 如果不是的话,你已经取消了上半场。
- 选取数组剩余部分的中间元素,然后继续执行第2步,排除剩余数组的一半。 最终你会发现你的元素,或没有数组留下来看。
二进制search的运行时间与数组长度的对数成正比,所以它比查看每个单独的元素要快得多。
假设.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
使用第二个参数(标志)强制值的比较,而不是参考
以下是您的一些元知识 – 如果您想知道如何使用数组,请查看文档 – 这里是Mozilla的Array页面
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array
在这里你会看到对indexOf的引用,在Javascript 1.6中添加
这取决于你的目的。 如果您为Web编程,请避免使用indexOf
,Internet Explorer 6不支持它们(它们中的很多仍在使用!),或者做有条件的使用:
if (yourArray.indexOf !== undefined) result = yourArray.indexOf(target); else result = customSlowerSearch(yourArray, target);
indexOf
可能是用本地代码编写的,所以它比在JavaScript中可以做的任何事都快(除非二进制search/二分法,如果数组是合适的)。 注:这是一个味道的问题,但我会做一个return false;
在你的例程结束,返回一个真正的布尔…
在这里详细介绍一种可靠的方法来检查一个对象是否是一个JavaScript中的数组:
下面是我附加到utils = {}
'容器'的xa.js框架中的两个函数。 这些应该会帮助你正确地检测数组。
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; }