Лучший способ найти, если элемент находится в массиве 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
549   8  

8 ответов:

начиная с ECMAScript 2016 вы можете использовать includes()

arr.includes(obj);

если вы хотите поддерживать IE или другие устаревшие браузеры:

function include(arr,obj) {
    return (arr.indexOf(obj) != -1);
}

изменить: Это не будет работать на IE6, 7 или 8 хотя бы. Лучший обходной путь-определить его самостоятельно, если его нет:

  1. 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;
      };
    
    }
    
  2. Дэниел Джеймс ' 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;
      };
    }
    
  3. 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, который, я думаю, составляет то же самое). Если массив отсортирован, вы можете выполнить двоичный поиск, который работает следующим образом:

  1. выбрать средний элемент массива.
  2. - Это элемент, который вы ищете больше, чем элемент, который вы выбрали? Если это так, вы устранили нижнюю половину массива. Если это не так, вы устранили топ половина.
  3. выберите средний элемент оставшейся половины массива и продолжайте, как в шаге 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

    Ничего не найдено.