Лучший способ узнать, находится ли элемент в массиве JavaScript?

Как лучше всего определить, находится ли объект в массиве?

Это лучший способ, который я знаю:

function include(arr, obj) {
  for (var i = 0; i < arr.length; i++) {
    if (arr[i] == obj) return true;
  }
}

console.info(include([1, 2, 3, 4], 3)); // true
console.info(include([1, 2, 3, 4], 6)); // undefined

См .: stackoverflow.com/a/25765186/1320932

dr.dimitru 10.09.2014 16:18

2 вещи: 1. 'include' - плохое название для функции, которая ничего не меняет. Это особенно плохо для функции, которая просто возвращает логическое значение. 2.) Вам нужно добавить «return (false);» перед окончанием функции.

Aquarelle 12.05.2015 03:57

с ECMAScript 2016 вы можете использовать функцию Array.prototype.includes: myArray.includes (3); // правда

mhd 15.06.2016 16:25

В ES6 вы можете сделать что-то вроде array.find (лямбда-функция), например: [1, 2, 3,4,5] .find (x => x == 3). если элемент найден, он возвращается, иначе возвращается undefined

allsyed 29.07.2016 13:26

arr.some (element => element === obj); some - лучший способ, потому что когда он находит элемент, а затем разрывает цикл.

Cenk Çetinkaya 09.01.2018 14:58
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
801
5
1 065 538
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. Версия Дэниел Джеймс:

     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. Версия петушок:

     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 так отличается от веб-сайта, на который вы ссылаетесь. Вы сами его модифицировали или это просто старая версия или что-то в этом роде?

Justin G 11.03.2014 05:16

@Shenjoku: "ответил 27 сен '08 в 15:45"

Vinko Vrsalovic 11.03.2014 09:49

Ну вот и мой ответ, ха-ха. Я не могу сказать, есть ли более старая версия, просто взглянув на веб-сайт Mozilla, поэтому я не был уверен. Не то чтобы это имело значение, просто любопытство. В любом случае это все еще было полезно, так что вы получите положительный голос;)

Justin G 13.03.2014 06:24

@Vinko Vrsalovic Да, это хорошее решение, но вам следует скрыть встроенную реализацию функции indexOf (), которая возвращает -1 с помощью оператора ~: function include (arr, obj) {return !! (~ arr.indexOf (obj)); }

KRRySS 02.08.2017 14:53

но, поскольку когда indexOf совместим с IE, потому что я обнаружил, что он совместим с IE w3schools.com/jsref/jsref_indexof.asp

ruselli 24.08.2017 16:18

@VinkoVrsalovic, как мне изменить эту функцию function include (arr, obj) {return (arr.indexOf (obj)! = -1); } Чтобы вернуть истину или ложь при передаче нескольких значений, например, двух строк? : D

Rich Cuer 19.02.2020 04:03

Если массив не отсортирован, лучшего способа на самом деле нет (кроме использования вышеупомянутого indexOf, что, как мне кажется, равносильно тому же). Если массив отсортирован, вы можете выполнить двоичный поиск, который работает следующим образом:

  1. Выберите средний элемент массива.
  2. Элемент, который вы ищете, больше, чем выбранный вами элемент? Если да, то вы удалили нижнюю половину массива. Если это не так, вы удалили верхнюю половину.
  3. Выберите средний элемент оставшейся половины массива и продолжайте, как на шаге 2, удаляя половинки оставшегося массива. В конце концов вы либо найдете свой элемент, либо у вас не останется массива для просмотра.

Двоичный поиск выполняется по времени, пропорциональному логарифму длины массива, поэтому он может быть намного быстрее, чем просмотр каждого отдельного элемента.

Вы, вероятно, должны упомянуть, что этот подход будет быстрее работать с большими отсортированными массивами, чем с маленькими.

cllpse 28.09.2008 03:07

почему это будет медленнее на меньших массивах?

vidstige 22.08.2011 11:54

@vidstige: он имеет в виду, что он хорошо масштабируется, но не обязательно самый быстрый для небольших входов.

Lightness Races in Orbit 11.02.2014 16:53

Это выполняется за O (lg n), а не за O (n), что намного более масштабируемо.

bigpotato 22.09.2014 23:09

Вот некоторые мета-знания для вас - если вы хотите знать, что вы можете делать с массивом, проверьте документацию - вот страница Array для Mozilla

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

Там вы увидите ссылку на indexOf, добавленную в Javascript 1.6.

Странный URL-адрес руководства, содержащего информацию о Javascript 1.8 и более поздних версиях! :)

Vinko Vrsalovic 27.09.2008 19:56

это не касается массивов объектов, о которых спрашивал автор

29er 31.05.2012 10:12

@VinkoVrsalovic: URL-адрес изменился на developer.mozilla.org/en-US/docs/JavaScript/Reference/…

Dan Dascalescu 02.11.2012 06:14

Это зависит от вашей цели. Если вы программируете для Интернета, избегайте indexOf, он не поддерживается Internet Explorer 6 (многие из них все еще используются!) Или используйте условное использование:

if (yourArray.indexOf !== undefined) result = yourArray.indexOf(target);
else result = customSlowerSearch(yourArray, target);

indexOf, вероятно, закодирован в собственном коде, поэтому он быстрее, чем все, что вы можете сделать в JavaScript (кроме двоичного поиска / дихотомии, если массив подходит). Примечание: это вопрос вкуса, но я бы сделал return false; в конце вашей процедуры, чтобы вернуть истинное логическое значение ...

ха ... Мне страшно подумать, что на данный момент все еще существует клиент IE6 ...

beauXjames 15.08.2014 20:25

не должно быть «по состоянию на 2008 год», как на странице википедии, чтобы люди знали, что это утверждение, безусловно, устарело

allan.simon 05.05.2016 17:20

@ allan.simon Посмотрите на мой значок (и статистику) внизу моего ответа. Чуть выше есть «ответ 27 сен. 2008 в 16:28». Это называется датой, и люди, привыкшие к Stack Overflow, смотрят на эти даты, чтобы получать ответы с долей скептицизма ... Тем не менее, в моей местной публичной библиотеке на компьютерах все еще установлен IE6! (но, к счастью, кто-то установил Chrome!)

PhiLho 06.05.2016 01:36

Во-первых, внедрите 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 в комментариях, в тестовый поиск в массивах. Хотя они довольно грубые, полное расследование позволит протестировать массивы разных типов, разной длины и найти объекты, которые встречаются в разных местах.

Примеры кода, на которые вы ссылаетесь, работают медленно на больших массивах. См. Комментарии в моем примере реализации функции hasItem ().

cllpse 28.09.2008 03:06

Взгляните на эти тесты: blogs.sun.com/greimer/resource/loop-test.htm For-loop медленные. Но я думаю, что массивы, используемые в тестах, довольно большие :)

cllpse 28.09.2008 15:28

Я согласен. Я тоже довольно прагматичен. Но в случае оптимизации самых основ языка, я думаю, что это хороший дизайн, чтобы реализовать функциональность, максимально эффективную с точки зрения производительности.

cllpse 28.09.2008 19:14

используйте mozilla Array.indexOf polyfill: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

user1742529 22.02.2020 06:55

Если вы используете jQuery:

$.inArray(5 + 5, [ "8", "9", "10", 10 + "" ]);

Для получения дополнительной информации: http://api.jquery.com/jQuery.inArray/

Обратите внимание, что inArray неправильно употреблено, потому что он не возвращает логическое значение - он возвращает индекс первого найденного элемента. Поэтому, если вы проверяете, существует ли элемент, вы должны использовать if (-1 != $.inArray(...)) ....

johndodo 10.02.2017 10:51

Полезно, но я не думаю, что здесь правильный ответ. На мой взгляд, вопрос помечен как "javascript", что означает "ваниль". :)

iMe 01.11.2017 17:37

Здесь подробно описан надежный способ проверить, является ли объект массивом в 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]+)\]/, '').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;
}

Хотя это теоретически может ответить на вопрос, было бы предпочтительнее, чтобы включить сюда основные части ответа и предоставить ссылку для справки. Кроме того, когда вы копируете / вставляете один и тот же ответ только по ссылке сразу на несколько очень старых вопросов, это просто выглядит как спам.

Bill the Lizard 18.08.2011 16:48

Извините, Билл, я действительно не имел в виду, что это похоже на спам, и просто пытался обновить несколько старых вопросов по этой теме. Я отредактировал сообщение здесь, чтобы включить фактический ответ вместо ссылки.

Aaria Carter-Weir 22.08.2011 11:37

@ Билл, на самом деле перечитываю вопрос, это даже не отвечает на него. Я, должно быть, ошибся.

Aaria Carter-Weir 22.08.2011 11:40

[] .has (объект)

предполагая, что .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-го аргумента (флага) вызывает сравнение по значению вместо ссылки

сравнение сырых объектов

[o1].has(o2,true) // true if every level value is same

Другие вопросы по теме