Лучший способ найти, если элемент находится в массиве JavaScript? [дубликат]
этот вопрос уже есть ответ здесь:
каков наилучший способ найти, если объект находится в массиве?
Это лучший способ, который я знаю:
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
8 ответов:
начиная с ECMAScript 2016 вы можете использовать
includes()arr.includes(obj);если вы хотите поддерживать IE или другие устаревшие браузеры:
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; }; }Дэниел Джеймс ' s версия:
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'S версия:
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/
во-первых, реализовать
indexOfв JavaScript для браузеров, которые еще не имеют его. Например, см. массив экстры Эрика Арвидссона (кроме того,связанный пост в блоге). И тогда вы можете использовать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; };Я предпочитаю использовать стандартную функцию и оставляя такого рода микро-оптимизации, когда это действительно необходимо. Но если вы заинтересованы в микро-оптимизации, я адаптировал критерии что roosterononacid связан с в комментариях, чтобы тест поиск в массивах. Они довольно грубые, хотя полное исследование будет проверять массивы с разными типами, разной длиной и находить объекты, которые встречаются в разных местах.
Если массив несортирован, на самом деле нет лучшего способа (кроме использования вышеупомянутого indexOf, который, я думаю, составляет то же самое). Если массив отсортирован, вы можете выполнить двоичный поиск, который работает следующим образом:
- выбрать средний элемент массива.
- - Это элемент, который вы ищете больше, чем элемент, который вы выбрали? Если это так, вы устранили нижнюю половину массива. Если это не так, вы устранили топ половина.
- выберите средний элемент оставшейся половины массива и продолжайте, как в шаге 2, устраняя половины оставшегося массива. В конце концов вы либо найдете свой элемент, либо у вас не останется массива для просмотра.
двоичный поиск выполняется во времени, пропорциональном логарифму длины массива, поэтому он может быть намного быстрее, чем просмотр каждого отдельного элемента.
предполагая, что
.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использование 2-го arg (флаг) заставляет сравнение по значению вместо ссылки
Это зависит от вашей цели. Если вы программируете для Интернета, избегайте
indexOf, Он не поддерживается Internet Explorer 6 (Многие из них все еще используются!), или сделать условное использование:if (yourArray.indexOf !== undefined) result = yourArray.indexOf(target); else result = customSlowerSearch(yourArray, target);
indexOfвероятно, закодирован в машинном коде, поэтому он быстрее, чем все, что вы можете сделать в JavaScript (кроме двоичного поиска/дихотомии, если массив подходит). Примечание: это вопрос вкуса, но я бы сделалreturn false;В конце вашей процедуры, чтобы вернуть истинное логическое значение...
вот некоторые мета-знания для вас - если вы хотите знать, что вы можете сделать с массивом, проверьте документацию - вот страница выбора для Mozilla
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array
там вы увидите ссылку на indexOf, добавленную в Javascript 1.6
надежный способ проверить, является ли объект массивом в javascript, подробно описан здесь:
вот две функции из 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]+)\]/, '').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; }
Comments