Как проверить, включает ли массив значение в JavaScript?

avatar
brad
25 октября 2008 в 22:14
2911917
58
4422

Каков наиболее краткий и эффективный способ узнать, содержит ли массив JavaScript значение?

Это единственный известный мне способ сделать это:

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

Есть ли лучший и более краткий способ сделать это?

Источник
Jörn Berkefeld
2 июля 2012 в 11:56
54

только что протестировано: ваш способ на самом деле самый быстрый для всех браузеров: jsperf.com/find-element-in-obj-vs-array/2 (кроме предварительного сохранения длины a.в переменной), в то время как использование indexOf (как в $ .inArray) намного медленнее

lordvlad
2 октября 2013 в 07:59
18

многие ответили, что Array # indexOf - ваш лучший выбор. Но если вам нужно что-то, что может быть правильно преобразовано в логическое значение, используйте это: ~[1,2,3].indexOf(4) вернет 0, который будет оцениваться как ложь, тогда как ~[1,2,3].indexOf(3) вернет -3, который будет оцениваться как истина.

mcfedr
20 июня 2014 в 12:49
9

~ - это не то, что вы хотите использовать для преобразования в логическое значение, для этого вам понадобится !. Но в этом случае вы хотите проверить равенство с -1, так как функция может закончиться return [1,2,3].indexOf(3) === -1; ~ не является двоичным, она будет инвертировать каждый бит значения индивидуально.

LCJ
21 января 2015 в 21:42
1

IE9 поддерживает indexOf() согласно w3schools.com/jsref/jsref_indexof_array.asp. Если в более старом браузере лучше всего определить prototype для функции indexOf(), как указано в Array.indexOf в Internet Explorer

mknecht
14 марта 2015 в 05:35
16

@Iordvlad [1,2,3].indexOf(4) фактически вернет -1. Как указал @mcfedr, ~ - это побитовый оператор НЕ, см. ES5 11.4.8. Дело в том, что поскольку двоичное представление -1 состоит только из единиц, его дополнение составляет 0, что оценивается как ложное. Дополнение любого другого числа будет отличным от нуля, следовательно, истинным. Итак, ~ работает нормально и часто используется вместе с indexOf.

mplungjan
2 апреля 2017 в 09:20
6

Название вводит в заблуждение. Где [[1,2],[3,4]].includes([3,4])?

Chau Giang
5 июня 2019 в 10:36
1

@brad, когда я впервые прочитал ваш вопрос, я не мог понять вашу идею, объект здесь - это объект javascript или примитивное значение. Предположим, у меня есть массив: const arr = [1, 2, 3, { foo: 1}];. И arr.includes(1) // true, но arr.includes({ foo: 1 }) //false

RBT
18 июня 2019 в 09:51
1

Если элементы в вашем массиве являются объектами , посмотрите этот ответ, в котором используется функция some.

Jakaria Ridoy
29 апреля 2020 в 10:01
0

let arr = ['apple','banana', 1, 2, 4] if (!arr.includes('banana') ) console.log('No') else console.log('Yes')

Ali NajafZadeh
3 августа 2021 в 16:56
0

console.log (['Джо', 'Джейн', 'Мэри']. включает ('Джейн'));

Ответы (58)

avatar
codeape
3 ноября 2020 в 17:51
4868

Современные браузеры имеют Array#includes, что делает ровно , а широко поддерживается всеми, кроме IE: <974390526490

console.log(['joe', 'jane', 'mary'].includes('jane')); //true

Вы также можете использовать Array#indexOf, который менее прямой, но не требует полифиллов для устаревших браузеров.

console.log(['joe', 'jane', 'mary'].indexOf('jane') >= 0); //true

Многие платформы также предлагают аналогичные методы:

Обратите внимание, что некоторые платформы реализуют это как функцию, в то время как другие добавляют функцию к прототипу массива.

Ryan Florence
8 июня 2010 в 14:10
45

В MooTools также есть Array.contains, который возвращает логическое значение, что здесь звучит как настоящий вопрос.

user102008
10 сентября 2010 в 22:54
23

прототип также имеет Array.include, который возвращает логическое значение

Sam Soffes
6 октября 2010 в 16:17
47

Если вы используете хороший браузер, вы можете просто использовать array.indexOf(object) != -1

zcrar70
12 июля 2011 в 10:06
1

@ user102008: MDN не содержит ссылки на Array.include (Ссылка на массив MDN - я искал, какая версия JS была в нем.) Где вы видели ссылку на этот метод?

plus-
29 февраля 2012 в 17:17
13

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

Tim
22 июля 2012 в 09:45
251

inArray - ужасное имя для функции, возвращающей индекс элемента, и -1, если его не существует. Я ожидал, что будет возвращено логическое значение.

Om Shankar
30 декабря 2012 в 18:54
1

var inArray = function(a,b,c,d){for(c in b)d|=b[c]===a;return!!d }

jcolebrand
16 января 2013 в 04:04
1

убрать подчеркивание включил?

codeape
16 января 2013 в 09:11
1

@jcolebrand Я обновил ответ. include все еще существует, но в документации указан как псевдоним для contains

Relequestual
19 августа 2013 в 12:46
2

@Tim, я думаю, он возвращает -1, чтобы свести на нет вероятность того, что 0 будет принят как ложь

Aaron Mason
10 июля 2014 в 23:15
1

Я думаю, что кто-то упомянул, что вы можете получить около 0, которое будет оценено как ложное, используя оператор ===, хотя бы мимоходом.

DanielST
21 октября 2014 в 20:31
1

Я думал, что дротик - это родной язык. Он действительно компилируется в JS? Изменить: о, его можно скомпилировать в JS, хотя он лучше всего работает в браузере, созданном для его запуска.

Witiko
21 марта 2015 в 15:44
11

@IulianOnofrei: Нет, 2 in [1,2,3] == true, но 5 in [3,4,5] == false. Почему? Поскольку массивы в сценариях JavaScripts ведут себя так же, как обычные объекты, поэтому 2 in array фактически означает только то, что array[2] определен. Имейте в виду, что это поведение все еще потенциально полезно, поскольку массивы JavaScript могут быть разреженными: 2 in [1,2,,3] == false

AlicanC
6 апреля 2015 в 13:09
0

Вы также должны проверить это предложение: github.com/tc39/Array.prototype.includes Также это для различных способов использования Array.prototype.indexOf(): codereview.stackexchange.com/questions/13941/…

Avatar
7 апреля 2015 в 15:50
1

Почему бы не привести в ответ пример? if($.inArray(value, array)) > -1 { // found value in array }

Adi Prasetyo
29 февраля 2016 в 18:47
2

сейчас 2016, и я все еще не могу правильно использовать .include и .indexOf для типа non primitive.

Kay Gee
12 октября 2018 в 16:23
1

Но ничего из этого не будет работать для массива сложного типа? он работает для строк, чисел и всего, что примерно так var arr = [{"id": "1", "name": "Joe"}, {"id": "2", "name": "Smith"} ]; var obj = {"id": "1", "name": "Joe"}; arr.includes (obj);

Stophface
24 октября 2018 в 06:40
7

array.includes(foo) не поддерживает объекты. Я не уверен, почему это принятый ответ, потому что его спросили Как мне проверить, включает ли массив объект в JavaScript?

Tomasz Smykowski
21 марта 2019 в 14:20
2

"широко" вводит в заблуждение, поскольку IE 11 его не поддерживает

user985399
26 июня 2019 в 15:03
1

Мне просто нужно запомнить indexOf для стендов Array и String :) на всякий случай.

Kapil soni
2 июля 2019 в 04:51
1

как проверить ключ и значение с помощью включения?

Sandro Schaurer
10 июля 2019 в 09:47
1

возможно, используйте IndexOf ^^

Emobe
2 августа 2019 в 21:30
3

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

Robert
7 января 2020 в 21:25
1

@Stophface @Emobe Как это может быть неправильный ответ? В вопросе задавались способы сделать то же самое, что и в предоставленном коде. И Array#includes делает именно то, что делает код в вопросе.

ow3n
17 сентября 2020 в 15:41
0

Отличный ответ. ПРИМЕЧАНИЕ: includesindexOf) НЕ преобразовывайте тип. Вам нужно будет сделать это в коде, я полагаю, console.log(['joe', 'jane', 'mary', 46].includes(Number('46')));

avatar
Rohìt Jíndal
18 мая 2022 в 05:51
0

Если вы просто пытаетесь проверить, включено ли значение в коллекцию, было бы более уместно использовать Set, поскольку Arrays может иметь повторяющиеся значения, тогда как Sets не может. Кроме того, замена array.includes на set.has повышает производительность с O(n2) до O(n). Это будет полезно, когда вам нужно найти несколько значений для одного и того же набора. поэтому, если вы просто собираетесь искать одно значение, нет смысла использовать set.has, вы можете просто использовать array.includes.

Создано демо jsbench. Вы можете запустить его, чтобы проверить производительность.

Скриншот выполнения теста :

enter image description here

avatar
Ran Turner
31 декабря 2021 в 15:03
0

Для этого есть несколько вариантов, включая includes, some, find, findIndex.

const array = [1, 2, 3, 4, 5, 6, 7];

console.log(array.includes(3));
//includes() determines whether an array includes a certain value among its entries

console.log(array.some(x => x === 3)); 
//some() tests if at least one element in the array passes the test implemented by the provided function

console.log(array.find(x => x === 3) ? true : false);
//find() returns the value of the first element in the provided array that satisfies the provided testing function

console.log(array.findIndex(x => x === 3) > -1 ? true : false);
//findIndex() returns the index of the first element in the array that satisfies the provided testing function, else returning -1.
avatar
Med Aziz CHETOUI
17 декабря 2021 в 06:45
1

Лучший метод по умолчанию для проверки существования значения в массиве JavaScript: some()

Array.prototype.some()

Метод some() проверяет, проходит ли хотя бы один элемент в массиве проверку, реализованную предоставленной функцией. Он возвращает true, если в массиве находит элемент, для которого предоставленная функция возвращает true; в противном случае возвращается ложь. Он не изменяет массив.

const array = [1, 2, 3, 4, 5];

// checks whether an element is even
const even = (element) => element % 2 === 0;

console.log(array.some(even));
// expected output: true

Метод some является лучшим в совместимости с браузером Browser compatibility

Дополнительная документация Array.prototype.some() - JavaScript | MDN

Также вы можете использовать два других метода: find() и includes(). этим методом можно получить свой результат, но не лучший.

Array.prototype.find() - JavaScript | MDN

Array.prototype.includes() - JavaScript | MDN

avatar
francis
23 июля 2021 в 13:55
0

Использование RegExp:

console.log(new RegExp('26242').test(['23525', '26242', '25272'].join(''))) // true
avatar
MsiLucifer
14 декабря 2020 в 17:33
0

Вы можете использовать функцию findIndex, чтобы проверить, имеет ли массив определенное значение.

arrObj.findIndex(obj => obj === comparedValue) !== -1;

Возвращает true, если arrObj содержит compareValue, в противном случае - false.

avatar
da coconut
8 июня 2020 в 10:21
5

используйте Array.prototype.includes, например:

const fruits = ['coconut', 'banana', 'apple']

const doesFruitsHaveCoconut = fruits.includes('coconut')// true

console.log(doesFruitsHaveCoconut)

, возможно, прочтите эту документацию из MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes

avatar
Md. Harun Or Rashid
24 мая 2020 в 09:48
3

Это может быть подробное и простое решение .

//plain array
var arr = ['a', 'b', 'c'];
var check = arr.includes('a');
console.log(check); //returns true
if (check)
{
   // value exists in array
   //write some codes
}

// array with objects
var arr = [
      {x:'a', y:'b'},
      {x:'p', y:'q'}
  ];

// if you want to check if x:'p' exists in arr
var check = arr.filter(function (elm){
    if (elm.x == 'p')
    {
       return elm; // returns length = 1 (object exists in array)
    }
});

// or y:'q' exists in arr
var check = arr.filter(function (elm){
    if (elm.y == 'q')
    {
       return elm; // returns length = 1 (object exists in array)
    }
});

// if you want to check, if the entire object {x:'p', y:'q'} exists in arr
var check = arr.filter(function (elm){
    if (elm.x == 'p' && elm.y == 'q')
    {
       return elm; // returns length = 1 (object exists in array)
    }
});

// in all cases
console.log(check.length); // returns 1

if (check.length > 0)
{
   // returns true
   // object exists in array
   //write some codes
}
avatar
Riwaj Chalise
24 апреля 2020 в 08:26
5

Используйте indexOf ()

Вы можете использовать метод indexOf (), чтобы проверить, существует ли данное значение или элемент в массиве или нет. Метод indexOf () возвращает индекс элемента внутри массива, если он найден, и возвращает -1, если он не найден. Давайте посмотрим на следующий пример:

var fruits = ["Apple", "Banana", "Mango", "Orange", "Papaya"];
var a = "Mango";
checkArray(a, fruits);


function checkArray(a, fruits) {
  // Check if a value exists in the fruits array
  if (fruits.indexOf(a) !== -1) {
    return document.write("true");
  } else {
    return document.write("false");
  }
}

Используйте метод include ()

ES6 представил метод includes () для очень простого выполнения этой задачи. Но этот метод возвращает только истину или ложь вместо номера индекса:

var fruits = ["Apple", "Banana", "Mango", "Orange", "Papaya"];
alert(fruits.includes("Banana")); // Outputs: true
alert(fruits.includes("Coconut")); // Outputs: false
alert(fruits.includes("Orange")); // Outputs: true
alert(fruits.includes("Cherry")); // Outputs: false

Для получения дополнительной информации обратитесь к здесь

avatar
Mamunur Rashid
26 января 2020 в 17:21
4

Добавление уникального элемента в другой список

searchResults: [
                {
                    name: 'Hello',
                    artist: 'Selana',
                    album: 'Riga',
                    id: 1,
                },
                {
                    name: 'Hello;s',
                    artist: 'Selana G',
                    album: 'Riga1',
                    id: 2,
                },
                {
                    name: 'Hello2',
                    artist: 'Selana',
                    album: 'Riga11',
                    id: 3,
                }
            ],
            playlistTracks: [
              {
                name: 'Hello',
                artist: 'Mamunuus',
                album: 'Riga',
                id: 4,
              },
              {
                name: 'Hello;s',
                artist: 'Mamunuus G',
                album: 'Riga1',
                id: 2,
              },
              {
                name: 'Hello2',
                artist: 'Mamunuus New',
                album: 'Riga11',
                id: 3,
              }
            ],
            playlistName: "New PlayListTrack",
        };
    }

    // Adding an unique track in the playList
    addTrack = track => {
      if(playlistTracks.find(savedTrack => savedTrack.id === track.id)) {
        return;
      }
      playlistTracks.push(track);

      this.setState({
        playlistTracks
      })
    };
stefanowiczp
6 февраля 2020 в 14:30
6

При чем здесь заданный вопрос?

avatar
Majedur
23 января 2020 в 08:54
2

Object.keys для получения всех имен свойств объекта и фильтрации всех значений, которые полностью или частично совпадают с указанной строкой.

function filterByValue(array, string) {
  return array.filter(o =>
    Object.keys(o).some(k => o[k].toLowerCase().includes(string.toLowerCase())));
}

const arrayOfObject = [{
  name: 'Paul',
  country: 'Canada',
}, {
  name: 'Lea',
  country: 'Italy',
}, {
  name: 'John',
  country: 'Italy'
}];

console.log(filterByValue(arrayOfObject, 'lea')); // [{name: 'Lea', country: 'Italy'}]
console.log(filterByValue(arrayOfObject, 'ita')); // [{name: 'Lea', country: 'Italy'}, {name: 'John', country: 'Italy'}]

Вы также можете фильтровать по определенному ключу, например.

Object.keys(o).some(k => o.country.toLowerCase().includes(string.toLowerCase())));

Теперь вы можете просто проверить количество массивов после фильтрации, чтобы проверить, содержит ли значение значение.

Надеюсь, это поможет.

avatar
Kamil Kiełczewski
7 января 2020 в 11:51
34

Производительность

Сегодня 2020.01.07 я провожу тесты на MacOs HighSierra 10.13.6 на Chrome v78.0.0, Safari v13.0.4 и Firefox v71.0.0 для 15 выбранных решений. Выводы

  • решения на основе JSON, Set и, что удивительно, find (K, N, O) самые медленные во всех браузерах
  • es6 includes (F) работает быстро только на Chrome
  • решения на основе for (C, D) и indexOf (G, H) довольно быстры во всех браузерах на малых и больших массивах, поэтому, вероятно, они являются лучшим выбором для эффективного решения
  • решения, в которых индекс уменьшается во время цикла, (B) медленнее, вероятно, потому, что способ кеш-памяти процессора работает.
  • Я также провожу тест для большого массива, когда искомый элемент находился на позиции 66% длины массива, и решения на основе for (C, D, E) дают аналогичные результаты (~ 630 операций в секунду, но E на safari и firefox были на 10-20% медленнее, чем C и D)

Результаты

enter image description here

Подробности

Я выполняю 2 тестовых случая: для массива с 10 элементами и массива с 1 миллионом элементов. В обоих случаях мы помещаем искомый элемент в середину массива.

let log = (name,f) => console.log(`${name}: 3-${f(arr,'s10')}  's7'-${f(arr,'s7')}  6-${f(arr,6)} 's3'-${f(arr,'s3')}`)

let arr = [1,2,3,4,5,'s6','s7','s8','s9','s10'];
//arr = new Array(1000000).fill(123); arr[500000]=7;

function A(a, val) {
    var i = -1;
    var n = a.length;
    while (i++<n) {
       if (a[i] === val) {
           return true;
       }
    }
    return false;
}

function B(a, val) {
    var i = a.length;
    while (i--) {
       if (a[i] === val) {
           return true;
       }
    }
    return false;
}

function C(a, val) {
    for (var i = 0; i < a.length; i++) {
        if (a[i] === val) return true;
    }
    return false;
}

function D(a,val)
{
    var len = a.length;
    for(var i = 0 ; i < len;i++)
    {
        if(a[i] === val) return true;
    }
    return false;
} 

function E(a, val){  
  var n = a.length-1;
  var t = n/2;
  for (var i = 0; i <= t; i++) {
        if (a[i] === val || a[n-i] === val) return true;
  }
  return false;
}

function F(a,val) {
	return a.includes(val);
}

function G(a,val) {
	return a.indexOf(val)>=0;
}

function H(a,val) {
	return !!~a.indexOf(val);
}

function I(a, val) {
  return a.findIndex(x=> x==val)>=0;
}

function J(a,val) {
	return a.some(x=> x===val);
}

function K(a, val) {
  const s = JSON.stringify(val);
  return a.some(x => JSON.stringify(x) === s);
}

function L(a,val) {
	return !a.every(x=> x!==val);
}

function M(a, val) {
  return !!a.find(x=> x==val);
}

function N(a,val) {
	return a.filter(x=>x===val).length > 0;
}

function O(a, val) {
  return new Set(a).has(val);
}

log('A',A);
log('B',B);
log('C',C);
log('D',D);
log('E',E);
log('F',F);
log('G',G);
log('H',H);
log('I',I);
log('J',J);
log('K',K);
log('L',L);
log('M',M);
log('N',N);
log('O',O);
This shippet only presents functions used in performance tests - it not perform tests itself!

Массив маленький - 10 элементов

Вы можете выполнять тесты на своем компьютере ЗДЕСЬ

enter image description here

Массив большой - 1.000.000 элементов

Вы можете проводить тесты на своем компьютере ЗДЕСЬ

enter image description here

avatar
Shiva
11 октября 2019 в 17:38
8

Простым решением для этого требования является использование find()

Если у вас есть массив объектов, как показано ниже,

var users = [{id: "101", name: "Choose one..."},
{id: "102", name: "shilpa"},
{id: "103", name: "anita"},
{id: "104", name: "admin"},
{id: "105", name: "user"}];

Затем вы можете проверить, присутствует ли уже объект с вашим значением

let data = users.find(object => object['id'] === '104');

если данные равны нулю, тогда нет администратора, иначе он вернет существующий объект, как показано ниже.

{id: "104", name: "admin"}

Затем вы можете найти индекс этого объекта в массиве и заменить объект, используя приведенный ниже код.

let indexToUpdate = users.indexOf(data);
let newObject = {id: "104", name: "customer"};
users[indexToUpdate] = newObject;//your new object
console.log(users);

вы получите значение, как показано ниже

[{id: "101", name: "Choose one..."},
{id: "102", name: "shilpa"},
{id: "103", name: "anita"},
{id: "104", name: "customer"},
{id: "105", name: "user"}];

надеюсь, что это поможет кому-нибудь.

avatar
Sumer
7 апреля 2019 в 13:42
7

Удивлен, что в этот вопрос все еще не добавлен последний синтаксис, добавлены мои 2 цента.

Допустим, у нас есть массив объектов arrObj, и мы хотим найти в нем obj.

Array.prototype. indexOf -> (возвращает index или -1 ) обычно используется для поиска индекса элемента в массиве. Это также можно использовать для поиска объекта, но работает только в том случае, если вы передаете ссылку на тот же объект.

let obj = { name: 'Sumer', age: 36 };
let arrObj = [obj, { name: 'Kishor', age: 46 }, { name: 'Rupen', age: 26 }];


console.log(arrObj.indexOf(obj));// 0
console.log(arrObj.indexOf({ name: 'Sumer', age: 36 })); //-1

console.log([1, 3, 5, 2].indexOf(2)); //3

Array.prototype. включает -> (возвращает true или false )

console.log(arrObj.includes(obj));  //true
console.log(arrObj.includes({ name: 'Sumer', age: 36 })); //false

console.log([1, 3, 5, 2].includes(2)); //true

Array.prototype. find -> (принимает обратный вызов, возвращает первое значение / объект , который возвращает true в CB).

console.log(arrObj.find(e => e.age > 40));  //{ name: 'Kishor', age: 46 }
console.log(arrObj.find(e => e.age > 40)); //{ name: 'Kishor', age: 46 }

console.log([1, 3, 5, 2].find(e => e > 2)); //3

Array.prototype. findIndex -> (принимает обратный вызов, возвращает индекс первого значения / объекта, возвращающего истину в CB).

console.log(arrObj.findIndex(e => e.age > 40));  //1
console.log(arrObj.findIndex(e => e.age > 40)); //1

console.log([1, 3, 5, 2].findIndex(e => e > 2)); //1

Поскольку find и findIndex принимают обратный вызов, мы можем получить любой объект (даже если у нас нет ссылки) из массива, творчески установив истинное условие.

avatar
Rajeev Ranjan
20 февраля 2019 в 12:03
5

Использование включает встроенную функцию javascript, но не работает в Internet Explorer

var optval = [];

optval.push('A');    
optval.push('B');    
optval.push('C');

Мы можем искать строку A в массиве javascript как:

optval.includes('A') // =====> return true
avatar
Sanjay Magar
15 декабря 2018 в 10:27
7

    function countArray(originalArray) {
     
    	var compressed = [];
    	// make a copy of the input array
    	var copyArray = originalArray.slice(0);
     
    	// first loop goes over every element
    	for (var i = 0; i < originalArray.length; i++) {
     
    		var count = 0;	
    		// loop over every element in the copy and see if it's the same
    		for (var w = 0; w < copyArray.length; w++) {
    			if (originalArray[i] == copyArray[w]) {
    				// increase amount of times duplicate is found
    				count++;
    				// sets item to undefined
    				delete copyArray[w];
    			}
    		}
     
    		if (count > 0) {
    			var a = new Object();
    			a.value = originalArray[i];
    			a.count = count;
    			compressed.push(a);
    		}
    	}
     
    	return compressed;
    };
    
    // It should go something like this:
    
    var testArray = new Array("dog", "dog", "cat", "buffalo", "wolf", "cat", "tiger", "cat");
    var newArray = countArray(testArray);
    console.log(newArray);
avatar
Nitesh Ranjan
29 октября 2018 в 16:42
3

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

let array = [1, 2, 3, 4, {"key": "value"}];

array.some((element) => JSON.stringify(element) === JSON.stringify({"key": "value"})) // true

array.some((element) => JSON.stringify(element) === JSON.stringify({})) // true

Array.some возвращает истину, если какой-либо элемент соответствует заданному условию, и возвращает ложь, если ни один из элементов не соответствует заданному условию.

Heretic Monkey
10 октября 2019 в 15:12
1

Позднее примечание: это не работает, скажем, с contains([{ a: 1, b: 2 }], { b: 2, a: 1 }), потому что строковые объекты поддерживают порядок свойств.

avatar
Shashwat Gupta
10 октября 2018 в 07:48
1

Простое решение: ES6 Features " включает " метод

let arr = [1, 2, 3, 2, 3, 2, 3, 4];

  arr.includes(2) // true

  arr.includes(93) // false
avatar
Durgpal Singh
26 июня 2018 в 10:03
4

Я рекомендовал использовать библиотеку подчеркивания, потому что она возвращает значение и поддерживается для всех браузеров.

underscorejs

 var findValue = _.find(array, function(item) {
    return item.id == obj.id;
 });
avatar
Neil Girardi
25 января 2018 в 04:03
4

Если вы работаете с ES6, вы можете использовать набор:

function arrayHas( array, element ) {
    const s = new Set(array);
    return s.has(element)
}

Этот метод должен быть более производительным, чем любой другой метод

Konstantin
30 марта 2018 в 07:43
3

Как он эффективнее? По крайней мере, вам нужно построить набор, который равен O (n) (вам нужно перебирать массив). Простой линейный поиск (например, indexOf) тоже O (n) , но только в худшем случае. Средняя сложность случая больше похожа на n / 2 , поскольку, если массив включает элемент, вы, вероятно, остановитесь где-то посередине. Следовательно, этот метод в среднем медленнее, чем Array#includes и Array#indexOf.

avatar
Mitul Panchal
5 декабря 2017 в 11:16
6

У него один параметр: массив номеров объектов. Каждый объект в массиве имеет два целочисленных свойства, обозначенных x и y. Функция должна возвращать количество всех таких объектов в массиве, которые удовлетворяют numbers.x == numbers.y

var numbers = [ { x: 1, y: 1 },
                { x: 2, y: 3 },
                { x: 3, y: 3 },
                { x: 3, y: 4 },
                { x: 4, y: 5 } ];
var count = 0; 
var n = numbers.length;
for (var i =0;i<n;i++)
{
  if(numbers[i].x==numbers[i].y)
    {count+=1;}
}

alert(count);
armand
13 июня 2018 в 13:32
0

Как бы вы сравнили значение x со значением x следующего элемента? Это не работает: for (var i = 0; i < n; i++) { if (numbers[i].x == (numbers[i] + 1).x) { count += 1; } }

avatar
Jeeva
5 сентября 2017 в 04:34
3

Я работал над проектом, в котором мне нужна была такая функциональность, как python set, которая удаляет все повторяющиеся значения и возвращает новый список, поэтому я написал, что эта функция может быть полезна кому-то

function set(arr) {
    var res = [];
    for (var i = 0; i < arr.length; i++) {
        if (res.indexOf(arr[i]) === -1) {
            res.push(arr[i]);
        }
    }
    return res;
}
avatar
Krishna Ganeriwal
18 августа 2017 в 04:20
5
  1. Либо используйте Array.indexOf(Object).
  2. В ECMA 7 можно использовать Array.includes(Object).
  3. В ECMA 6 вы можете использовать Array.find(FunctionName), где FunctionName - пользователь определенная функция для поиска объекта в массиве.

    Надеюсь, это поможет!

avatar
KRRySS
2 августа 2017 в 11:57
3

Использование idnexOf () - хорошее решение, но вам следует скрыть встроенную функцию indexOf () реализации, которая возвращает -1 с помощью оператора ~:

function include(arr,obj) { 
    return !!(~arr.indexOf(obj)); 
} 
avatar
Alireza
2 июля 2017 в 11:31
7

Хорошо, вы можете просто оптимизировать свой код , чтобы получить результат!

Есть много способов сделать это чище и лучше, но я просто хотел получить ваш шаблон и применить к нему с помощью JSON.stringify, просто сделайте что-то вроде этого в вашем случае:

function contains(a, obj) {
    for (var i = 0; i < a.length; i++) {
        if (JSON.stringify(a[i]) === JSON.stringify(obj)) {
            return true;
        }
    }
    return false;
}
Heretic Monkey
10 октября 2019 в 15:12
1

Позднее примечание: это не работает, скажем, с contains([{ a: 1, b: 2 }], { b: 2, a: 1 }), потому что строковые объекты поддерживают порядок свойств.

avatar
Maxime Helen
19 июня 2017 в 00:41
4

Или это решение:

Array.prototype.includes = function (object) {
  return !!+~this.indexOf(object);
};
avatar
Igor Barbashin
25 января 2017 в 00:22
16

Решение, работающее во всех современных браузерах:

function contains(arr, obj) {
  const stringifiedObj = JSON.stringify(obj); // Cache our object to not call `JSON.stringify` on every iteration
  return arr.some(item => JSON.stringify(item) === stringifiedObj);
}

Использование:

contains([{a: 1}, {a: 2}], {a: 1}); // true

Решение IE6 +:

function contains(arr, obj) {
  var stringifiedObj = JSON.stringify(obj)
  return arr.some(function (item) {
    return JSON.stringify(item) === stringifiedObj;
  });
}

// .some polyfill, not needed for IE9+
if (!('some' in Array.prototype)) {
  Array.prototype.some = function (tester, that /*opt*/) {
    for (var i = 0, n = this.length; i < n; i++) {
      if (i in this && tester.call(that, this[i], i, this)) return true;
    } return false;
  };
}

Использование:

contains([{a: 1}, {a: 2}], {a: 1}); // true

Зачем использовать JSON.stringify?

Array.indexOf и Array.includes (а также большинство ответов здесь) сравниваются только по ссылке, а не по значению.

[{a: 1}, {a: 2}].includes({a: 1});
// false, because {a: 1} is a new object

Бонус

Неоптимизированный однострочник ES6:

[{a: 1}, {a: 2}].some(item => JSON.stringify(item) === JSON.stringify({a: 1));
// true

Примечание: Сравнение объектов по значению будет работать лучше, если ключи находятся в одном порядке, поэтому для безопасности вы можете сначала отсортировать ключи с помощью такого пакета: https://www.npmjs.com/package/sort- ключи


Обновлена ​​функция contains с оптимизацией производительности. Спасибо itinance за указание на это.

Mark Reed
9 апреля 2017 в 12:51
0

Этот конкретный фрагмент кода может работать в IE6 (не тестировался), но IE не поддерживал ES5 до IE9.

itinance
14 апреля 2017 в 08:45
0

По соображениям производительности вам следует избегать стягивания. По крайней мере, вам следует избегать JSON.stringify "obj" в каждом цикле, потому что это дорого и замедлит ваше приложение. Поэтому вы должны захватить его перед циклом for во временной переменной.

Igor Barbashin
17 апреля 2017 в 04:57
2

@itinance хороший момент. Обновлена ​​функция includes с учетом вашего предложения. Я запустил jsperf со своей функцией. Это примерно в 5 раз медленнее, чем у lodash. Хотя lodash не сравнивается по значению и не может найти {a: 1} в [{a: 1}]. Я не знаю, делает ли это какая-нибудь библиотека. Но мне любопытно, есть ли еще эффективный и не безумно сложный способ сделать это.

Heretic Monkey
10 октября 2019 в 15:10
0

Позднее примечание: это не работает, скажем, с contains([{ a: 1, b: 2 }], { b: 2, a: 1 }), потому что строковые объекты поддерживают порядок свойств.

Igor Barbashin
16 октября 2019 в 17:44
2

@HereticMonkey, правда. Вот почему я добавил заметку sort-keys внизу

avatar
user2724028
10 января 2016 в 10:06
5

Вы также можете использовать этот трюк:

var arrayContains = function(object) {
  return (serverList.filter(function(currentObject) {
    if (currentObject === object) {
      return currentObject
    }
    else {
      return false;
    }
  }).length > 0) ? true : false
}
TygerKrash
5 августа 2016 в 11:15
0

это кажется запутанным. «объект» - плохое название, «предмет» могло бы быть лучше. логика функции фильтра должна просто возвращать currentObject === item; и тернарный оператор не нужен ..

avatar
sqram
9 января 2016 в 06:38
6

Ни в коем случае не лучший, но я просто проявил творческий подход и добавил к репертуару.

Не используйте это

Object.defineProperty(Array.prototype, 'exists', {
  value: function(element, index) {

    var index = index || 0

    return index === this.length ? -1 : this[index] === element ? index : this.exists(element, ++index)
  }
})


// Outputs 1
console.log(['one', 'two'].exists('two'));

// Outputs -1
console.log(['one', 'two'].exists('three'));

console.log(['one', 'two', 'three', 'four'].exists('four'));
bryc
20 февраля 2017 в 17:36
0

Что использовать, если не это?

sqram
16 марта 2017 в 19:49
0

@bryc, возможно, принятое решение или другое решение отсюда. Если вам не важна производительность, вы можете использовать это

avatar
rlib
16 ноября 2015 в 12:26
10

Можно использовать Набор, у которого есть метод has ():

function contains(arr, obj) {
      var proxy = new Set(arr);
      if (proxy.has(obj))
        return true;
      else
        return false;
    }

    var arr = ['Happy', 'New', 'Year'];
    console.log(contains(arr, 'Happy'));
Maciej Bukowski
18 августа 2016 в 23:30
8

Я думаю, что return proxy.has(obj) намного чище, чем две строки с выражением if-else здесь

Gordon Bean
11 марта 2020 в 15:48
1

function contains(arr, obj) { return new Set(arr).has(obj); }

avatar
l3x
21 октября 2015 в 10:57
12

Используйте lodash какую-нибудь функцию.

Он краток, точен и имеет отличную кроссплатформенную поддержку.

Принятый ответ даже не соответствует требованиям.

Требования: Рекомендовать наиболее краткий и эффективный способ узнать, содержит ли массив JavaScript объект.

Принятый ответ:

$.inArray({'b': 2}, [{'a': 1}, {'b': 2}])
> -1

Моя рекомендация:

_.some([{'a': 1}, {'b': 2}], {'b': 2})
> true

Примечания:

$ .inArray отлично подходит для определения наличия скалярного значения в массиве скаляров ...

$.inArray(2, [1,2])
> 1

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

Чтобы обрабатывать как скаляры, так и объекты, вы можете сделать следующее:

(_.isObject(item)) ? _.some(ary, item) : (_.indexOf(ary, item) > -1)
avatar
cocco
19 мая 2015 в 20:23
19

Надеемся, более быстрый двунаправленный indexOf / lastIndexOf альтернатива

2015

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

Я давно думал о том, как заменить медленные функции indexOf / lastIndexOf.

Эффективный способ уже найден, если посмотреть на самые популярные ответы. Из них я выбрал функцию contains, опубликованную @Damir Zekic, которая должна быть самой быстрой. Но в нем также указано, что тесты датируются 2008 годом и поэтому устарели.

Я также предпочитаю while, а не for, но не по какой-то конкретной причине я закончил писать функцию с помощью цикла for. Это также можно сделать с помощью while --.

Мне было любопытно, будет ли итерация намного медленнее, если я при этом проверю обе стороны массива. По-видимому, нет, и поэтому эта функция примерно в два раза быстрее, чем у самых популярных. Очевидно, он также быстрее родного. Это в реальной среде, где вы никогда не узнаете, находится ли искомое значение в начале или в конце массива.

Когда вы знаете, что просто отправили массив со значением, использование lastIndexOf, вероятно, остается лучшим решением, но если вам нужно перемещаться по большим массивам, и результат может быть везде, это может быть надежным решением для ускорения работы.

Двунаправленный indexOf / lastIndexOf

function bidirectionalIndexOf(a, b, c, d, e){
  for(c=a.length,d=c*1; c--; ){
    if(a[c]==b) return c; //or this[c]===b
    if(a[e=d-1-c]==b) return e; //or a[e=d-1-c]===b
  }
  return -1
}

//Usage
bidirectionalIndexOf(array,'value');

Тест производительности

http://jsperf.com/bidirectionalindexof

В качестве теста я создал массив из 100 тыс. Записей.

Три запроса: в начале, в середине и в конце массива.

Надеюсь, вам это тоже понравится, и вы протестируете производительность.

Примечание. Как вы можете видеть, я немного изменил функцию contains, чтобы отразить вывод indexOf и lastIndexOf (поэтому в основном true с index и false с -1). Это не должно повредить ему.

Вариант прототипа массива

Object.defineProperty(Array.prototype,'bidirectionalIndexOf',{value:function(b,c,d,e){
  for(c=this.length,d=c*1; c--; ){
    if(this[c]==b) return c; //or this[c]===b
    if(this[e=d-1-c] == b) return e; //or this[e=d-1-c]===b
  }
  return -1
},writable:false, enumerable:false});

// Usage
array.bidirectionalIndexOf('value');

Функцию также можно легко изменить, чтобы она возвращала истину или ложь или даже объект, строку или что-то еще.

А вот вариант while:

function bidirectionalIndexOf(a, b, c, d){
  c=a.length; d=c-1;
  while(c--){
    if(b===a[c]) return c;
    if(b===a[d-c]) return d-c;
  }
  return c
}

// Usage
bidirectionalIndexOf(array,'value');

Как это возможно?

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

Вот сложный пример, выполняющий три проверки на итерацию, но это возможно только при более длительном вычислении, которое вызывает замедление кода.

http://jsperf.com/bidirectionalindexof/2

avatar
AlonL
7 января 2015 в 12:49
34

Однострочник:

function contains(arr, x) {
    return arr.filter(function(elem) { return elem == x }).length > 0;
}
Apolo
22 апреля 2016 в 09:22
10

array.filter(e=>e==x).length > 0 эквивалентен array.some(e=>e==x), но some более эффективен

avatar
Oriol
1 января 2015 в 01:40
184

ECMAScript 7 вводит Array.prototype.includes.

Его можно использовать так:

[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false

Он также принимает необязательный второй аргумент fromIndex:

[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true

В отличие от indexOf, в котором используется Строгое сравнение равенства, includes сравнивается с использованием SameValueZero алгоритма равенства. Это означает, что вы можете определить, содержит ли массив NaN:

[1, 2, NaN].includes(NaN); // true

Также в отличие от indexOf, includes не пропускает отсутствующие индексы:

new Array(5).includes(undefined); // true

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

Adriano Resende
5 ноября 2015 в 23:04
4

Не поддерживается для IE и Microsoft Edge (2015) (developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…)

styfle
11 марта 2016 в 20:25
2

Также актуальна таблица совместимости ES7 (похоже, что Chrome теперь поддерживает)

Himesh Aadeshara
25 мая 2018 в 04:18
0

применимо ли это для проверки объекта? я не думаю, что это работает в случае объекта

avatar
dansalmo
12 сентября 2014 в 16:55
24
function contains(a, obj) {
    return a.some(function(element){return element == obj;})
}

Array.prototype.some () был добавлен в стандарт ECMA-262 в 5-м издании

diEcho
28 мая 2018 в 04:24
0

при использовании es6 его можно сократить до contains = (a, obj) => a.some((element) => element === obj))

Suncat2000
17 января 2019 в 17:45
0

Даже IE9 поддерживает Array.prototype.some () начиная с ECMAScript 5 .

avatar
dr.dimitru
10 сентября 2014 в 12:12
16

Мы используем этот сниппет (работает с объектами, массивами, строками):

/*
 * @function
 * @name Object.prototype.inArray
 * @description Extend Object prototype within inArray function
 *
 * @param {mix}    needle       - Search-able needle
 * @param {bool}   searchInKey  - Search needle in keys?
 *
 */
Object.defineProperty(Object.prototype, 'inArray',{
    value: function(needle, searchInKey){

        var object = this;

        if( Object.prototype.toString.call(needle) === '[object Object]' || 
            Object.prototype.toString.call(needle) === '[object Array]'){
            needle = JSON.stringify(needle);
        }

        return Object.keys(object).some(function(key){

            var value = object[key];

            if( Object.prototype.toString.call(value) === '[object Object]' || 
                Object.prototype.toString.call(value) === '[object Array]'){
                value = JSON.stringify(value);
            }

            if(searchInKey){
                if(value === needle || key === needle){
                return true;
                }
            }else{
                if(value === needle){
                    return true;
                }
            }
        });
    },
    writable: true,
    configurable: true,
    enumerable: false
});

Использование :

var a = {one: "first", two: "second", foo: {three: "third"}};
a.inArray("first");          //true
a.inArray("foo");            //false
a.inArray("foo", true);      //true - search by keys
a.inArray({three: "third"}); //true

var b = ["one", "two", "three", "four", {foo: 'val'}];
b.inArray("one");         //true
b.inArray('foo');         //false
b.inArray({foo: 'val'})   //true
b.inArray("{foo: 'val'}") //false

var c = "String";
c.inArray("S");        //true
c.inArray("s");        //false
c.inArray("2", true);  //true
c.inArray("20", true); //false
avatar
Michael
18 июля 2014 в 14:36
176

Первые ответы предполагают примитивные типы, но если вы хотите узнать, содержит ли массив объект с некоторой характеристикой, Array.prototype.some () - элегантное решение:

const items = [ {a: '1'}, {a: '2'}, {a: '3'} ]

items.some(item => item.a === '3')  // returns true
items.some(item => item.a === '4')  // returns false

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

Кроме того, он хорошо вписывается в инструкцию if, поскольку возвращает логическое значение:

if (items.some(item => item.a === '3')) {
  // do something
}

* Как указал Джеймс в комментарии, на момент этого ответа, сентябрь 2018 г., Array.prototype.some() полностью поддерживается: таблица поддержки caniuse.com

jamess
14 сентября 2018 в 22:03
2

На сегодняшний день, сентябрь 2018 г., Array.prototype.some () полностью поддерживается: таблица поддержки caniuse.com

Jordan
20 сентября 2018 в 22:48
2

Работа в Node> = 8.10 для AWS Node.js Lambda, так что это здорово. Очень чистое и простое решение! 👍🏻

Kamil Witkowski
24 января 2019 в 14:32
2

@jamess Может хорошо поддерживаться, но помните, что Arrow functions в этом примере не так хорошо поддерживается. Подробнее см. Здесь: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

Douglas Gaskell
3 октября 2019 в 00:06
0

Есть короткое замыкание? Или он перебирает весь массив, даже если он нашел значение?

Michael
14 октября 2019 в 12:28
0

@DouglasGaskell прерывает найденную итерацию (упоминается в ответе)

avatar
Eduardo Cuomo
15 июня 2014 в 01:15
28

Я использую следующее:

Array.prototype.contains = function (v) {
    return this.indexOf(v) > -1;
}

var a = [ 'foo', 'bar' ];

a.contains('foo'); // true
a.contains('fox'); // false
avatar
Pradeep Mahdevu
29 мая 2014 в 16:55
10

В ECMAScript 6 есть элегантное предложение по поиску.

Метод find выполняет функцию обратного вызова один раз для каждого элемента. присутствует в массиве, пока не найдет тот, где обратный вызов вернет истинное значение стоимость. Если такой элемент найден, find немедленно возвращает значение этого элемента. В противном случае find возвращает значение undefined. обратный звонок вызывается только для индексов массива, которым присвоены значения; Это не вызывается для индексов, которые были удалены или которые никогда не присвоены значения.

Вот документация MDN по этому поводу.

Функция поиска работает следующим образом.

function isPrime(element, index, array) {
    var start = 2;
    while (start <= Math.sqrt(element)) {
        if (element % start++ < 1) return false;
    }
    return (element > 1);
}

console.log( [4, 6, 8, 12].find(isPrime) ); // Undefined, not found
console.log( [4, 5, 8, 12].find(isPrime) ); // 5

Вы можете использовать это в ECMAScript 5 и ниже, определив функцию.

if (!Array.prototype.find) {
  Object.defineProperty(Array.prototype, 'find', {
    enumerable: false,
    configurable: true,
    writable: true,
    value: function(predicate) {
      if (this == null) {
        throw new TypeError('Array.prototype.find called on null or undefined');
      }
      if (typeof predicate !== 'function') {
        throw new TypeError('predicate must be a function');
      }
      var list = Object(this);
      var length = list.length >>> 0;
      var thisArg = arguments[1];
      var value;

      for (var i = 0; i < length; i++) {
        if (i in list) {
          value = list[i];
          if (predicate.call(thisArg, value, i, list)) {
            return value;
          }
        }
      }
      return undefined;
    }
  });
}
Madbreaks
16 августа 2016 в 17:38
1

Теперь это стандарт: ecma-international.org/ecma-262/6.0/#sec-array.prototype.find

avatar
Mina Gabriel
6 октября 2013 в 12:25
8

Использование:

var myArray = ['yellow', 'orange', 'red'] ;

alert(!!~myArray.indexOf('red')); //true

Демо

Чтобы точно знать, что делает tilde ~ на этом этапе, обратитесь к этому вопросу Что делает тильда, когда она предшествует выражению?

Shadow Wizard Wearing Mask V2
6 октября 2013 в 12:33
6

Это уже было опубликовано полтора года назад, повторять не нужно.

T.CK
15 мая 2018 в 14:52
4

На самом деле он не был опубликован. Не как ответ, а как комментарий к ответу, да и то нечетко и лаконично. Спасибо за публикацию, Мина Габриэль.

avatar
Matías Cánepa
13 сентября 2013 в 17:32
59

Использование:

function isInArray(array, search)
{
    return array.indexOf(search) >= 0;
}

// Usage
if(isInArray(my_array, "my_value"))
{
    //...
}
Ry-♦
26 февраля 2014 в 16:38
27

x ? true : false обычно избыточен. Это здесь.

Matías Cánepa
3 мая 2014 в 15:40
1

@minitech Почему вы говорите, что это лишнее?

Ry-♦
3 мая 2014 в 17:38
11

array.indexOf(search) >= 0 уже является логическим. Просто return array.indexOf(search) >= 0.

Matías Cánepa
29 июля 2014 в 18:25
1

@minitech ну спасибо! На самом деле я не знал, что такую ​​конструкцию можно вернуть. TIL что-то новое.

B T
15 января 2015 в 22:20
2

Буквально любая конструкция в javascript может быть возвращена

avatar
stamat
3 июля 2013 в 16:26
2

Я просмотрел представленные ответы и понял, что они применимы только в том случае, если вы ищете объект по ссылке. Простой линейный поиск со сравнением эталонных объектов.

Но, допустим, у вас нет ссылки на объект, как вы найдете правильный объект в массиве? Вам придется идти линейно и глубоко сравнивать каждый объект. Представьте, что список слишком велик, а объекты в нем очень большие и содержат большие фрагменты текста. Производительность резко падает с увеличением количества и размера элементов в массиве.

Вы можете структурировать объекты и поместить их в собственную хеш-таблицу, но тогда у вас будет избыточность данных, запомнив эти ключи, потому что JavaScript сохраняет их для 'for i in obj', и вы хотите только проверить, существует ли объект или нет , то есть ключ у вас.

Некоторое время я думал об этом, создав валидатор схемы JSON, и разработал простую оболочку для собственной хеш-таблицы, похожую на единственную реализацию хеш-таблицы, с некоторыми исключениями оптимизации, которые я оставил для работы с собственной хеш-таблицей. с. Нужен только тест производительности ... Все подробности и код можно найти в моем блоге: http://stamat.wordpress.com/javascript-quickly-find-very-large-objects-in-a-large-array/ Я скоро опубликую результаты тестов.

Полное решение работает следующим образом:

var a = {'a':1,
 'b':{'c':[1,2,[3,45],4,5],
 'd':{'q':1, 'b':{'q':1, 'b':8},'c':4},
 'u':'lol'},
 'e':2};

 var b = {'a':1, 
 'b':{'c':[2,3,[1]],
 'd':{'q':3,'b':{'b':3}}},
 'e':2};

 var c = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";

 var hc = new HashCache([{a:3, b:2, c:5}, {a:15, b:2, c:'foo'}]); //init

 hc.put({a:1, b:1});
 hc.put({b:1, a:1});
 hc.put(true);
 hc.put('true');
 hc.put(a);
 hc.put(c);
 hc.put(d);
 console.log(hc.exists('true'));
 console.log(hc.exists(a));
 console.log(hc.exists(c));
 console.log(hc.exists({b:1, a:1}));
 hc.remove(a);
 console.log(hc.exists(c));
avatar
Simon_Weaver
12 марта 2013 в 05:44
3

Как уже упоминалось другими, вы можете использовать Array.indexOf, но он доступен не во всех браузерах. Вот код из https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf, чтобы он работал так же в старых браузерах.

indexOf - недавнее дополнение к стандарту ECMA-262; как таковой это может присутствовать не во всех браузерах. Вы можете обойти это, вставив следующий код в начале ваших скриптов, позволяющий использовать indexOf в реализациях, которые его не поддерживают. Этот алгоритм в точности тот, который указан в ECMA-262, 5-е издание, при условии, что Object, TypeError, Number, Math.floor, Math.abs и Math.max имеют исходное значение.

if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
        "use strict";
        if (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 > 1) {
            n = Number(arguments[1]);
            if (n != n) { // shortcut for verifying if it's NaN
                n = 0;
            } else if (n != 0 && n != Infinity && n != -Infinity) {
                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;
    }
}
avatar
Andy Rohr
23 ноября 2012 в 16:44
3

Аналогичная вещь: находит первый элемент с помощью "лямбда-выражения поиска":

Array.prototype.find = function(search_lambda) {
  return this[this.map(search_lambda).indexOf(true)];
};

Использование:

[1,3,4,5,8,3,5].find(function(item) { return item % 2 == 0 })
=> 4

То же в coffeescript:

Array.prototype.find = (search_lambda) -> @[@map(search_lambda).indexOf(true)]
dat
5 июня 2013 в 21:28
0

Это, безусловно, гораздо более гибкий подход, чем многие другие подходы. Если прототип не устраивает, можно рассмотреть что-то вроде var positionIf = function (предикат, последовательность) {return sequence.map (predicate) .indexOf (true);};

Casey Chu
10 октября 2013 в 04:49
3

Более эффективный способ реализовать этот метод - использовать цикл и прекратить применение search_lambda, как только что-то будет найдено.

avatar
Lemex
27 июня 2012 в 12:32
17
function inArray(elem,array)
{
    var len = array.length;
    for(var i = 0 ; i < len;i++)
    {
        if(array[i] == elem){return i;}
    }
    return -1;
} 

Возвращает индекс массива, если найден, или -1, если не найден

avatar
ninjagecko
22 апреля 2012 в 05:17
10

Хотя array.indexOf(x)!=-1 является наиболее кратким способом сделать это (и уже более десяти лет поддерживается браузерами, отличными от Internet Explorer ...), это не O (1), а скорее O (N), что ужасно. Если ваш массив не будет изменяться, вы можете преобразовать его в хеш-таблицу, а затем выполните table[x]!==undefined или ===undefined:

Array.prototype.toTable = function() {
    var t = {};
    this.forEach(function(x){t[x]=true});
    return t;
}

Демо:

var toRemove = [2,4].toTable();
[1,2,3,4,5].filter(function(x){return toRemove[x]===undefined})

(К сожалению, хотя вы можете создать Array.prototype.contains, чтобы «заморозить» массив и сохранить хэш-таблицу в this._cache в двух строках, это даст неверные результаты, если вы решите изменить свой массив позже. JavaScript имеет недостаточно хуков, чтобы сохранить это состояние, в отличие, например, от Python.)

avatar
william malo
24 марта 2012 в 04:59
118

Допустим, вы определили массив следующим образом:

const array = [1, 2, 3, 4]

Ниже приведены три способа проверить, есть ли там 3. Все они возвращают либо true, либо false.

Метод собственного массива (начиная с ES2016) (таблица совместимости)

array.includes(3) // true

Как настраиваемый метод массива (до ES2016)

// Prefixing the method with '_' to avoid name clashes
Object.defineProperty(Array.prototype, '_includes', { value: function (v) { return this.indexOf(v) !== -1 }})
array._includes(3) // true

Простая функция

const includes = (a, v) => a.indexOf(v) !== -1
includes(array, 3) // true
william malo
16 июня 2012 в 00:41
0

Он возвращает истину, если "b" находится в массиве "a" ... Я не знаю, как еще это объяснить ...

svlada
18 июня 2012 в 05:29
4

Я не понимаю "!! ~". И я думаю, что это не сработает в IE8, потому что IE8 не поддерживает indexOf () для объекта Array.

william malo
19 июня 2012 в 14:41
63

«~» - это оператор, который увеличивает, инвертирует и вычитает 1 из числа. indexOf возвращает -1 в случае неудачи, поэтому "~" превращает -1 в "0". с использованием "!!" превращает числа в булевы (!! 0 === false)

user2039981
16 декабря 2014 в 15:35
1

Круто, но серьезно для простоты y не просто a.indexOf (b)> - 1, так как "> -1" .length === "!! ~" .length

okdewit
19 января 2016 в 11:18
2

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

avatar
Carlos A
6 января 2012 в 13:43
4

Использование:

Array.prototype.contains = function(x){
  var retVal = -1;

  // x is a primitive type
  if(["string","number"].indexOf(typeof x)>=0 ){ retVal = this.indexOf(x);}

  // x is a function
  else if(typeof x =="function") for(var ix in this){
    if((this[ix]+"")==(x+"")) retVal = ix;
  }

  //x is an object...
  else {
    var sx=JSON.stringify(x);
    for(var ix in this){
      if(typeof this[ix] =="object" && JSON.stringify(this[ix])==sx) retVal = ix;
    }
  }

  //Return False if -1 else number if numeric otherwise string
  return (retVal === -1)?false : ( isNaN(+retVal) ? retVal : +retVal);
}

Я знаю, что это не лучший способ, но, поскольку нет встроенного IComparable способа взаимодействия между объектами, я думаю, это максимально приближено к сравнению двух сущностей в массиве. Кроме того, расширение объекта Array может быть неразумным решением, но иногда это нормально (если вы знаете об этом и о компромиссе).

Heretic Monkey
10 октября 2019 в 15:13
0

Позднее примечание: это не работает, скажем, с contains([{ a: 1, b: 2 }], { b: 2, a: 1 }), потому что строковые объекты поддерживают порядок свойств.

avatar
Ekim
10 мая 2011 в 19:14
-4

Буквально:

(с использованием Firefox v3.6, с for-in оговорками, как отмечалось ранее (ОДНАКО приведенное ниже использование может поддерживать for-in именно для этой цели! То есть перечисление элементов массива, которые ДЕЙСТВИТЕЛЬНО существуют через индекс свойства (ОДНАКО, в частности, свойство массива length НЕ перечисляется в списке свойств for-in !).).)

(Перетащите следующие полные URI для немедленного тестирования браузера.)

JavaScript:

  function ObjInRA(ra){var has=false; for(i in ra){has=true; break;} return has;}

  function check(ra){
      return ['There is ',ObjInRA(ra)?'an':'NO',' object in [',ra,'].'].join('')
  }
  alert([
            check([{}]), check([]), check([,2,3]),
            check(['']), '\t (a null string)', check([, ,])
        ].join('\n'));

, который отображает:

There is an object in [[object Object]].
There is NO object in [].
There is an object in [,2,3].
There is an object in [].
     (a null string)
There is NO object in [, ].

Морщины: если вы ищете "конкретный" объект, подумайте:

JavaScript: alert({}!={}); alert({}!=={});

И таким образом:

JavaScript:

 obj = {prop:"value"}; 
 ra1 = [obj]; 
 ra2 = [{prop:"value"}];
 alert(ra1[0] == obj); 
 alert(ra2[0] == obj);

Часто считается, что ra2 "содержит" obj как буквальную сущность {prop:"value"}.

Очень грубое, рудиментарное, наивное (как в коде требует повышения квалификации) решение:

JavaScript:

  obj={prop:"value"};   ra2=[{prop:"value"}];
  alert(
    ra2 . toSource() . indexOf( obj.toSource().match(/^.(.*).$/)[1] ) != -1 ?
      'found' :
      'missing' );

См. Ссылку: Поиск объектов в массивах JavaScript .

avatar
Ztyx
5 февраля 2011 в 18:02
16

Если вы неоднократно проверяете наличие объекта в массиве, возможно, вам стоит посмотреть на

  1. Постоянное сохранение массива отсортированным путем выполнения сортировки вставкой в массиве (помещайте новые объекты в нужное место)
  2. Сделайте обновление объектов как операцию удаления + сортировки и вставки и
  3. Используйте бинарный поиск для поиска в вашем contains(a, obj).
joeytwiddle
8 июля 2013 в 17:08
3

Или, если возможно, полностью прекратите использование массива и вместо этого используйте объект в качестве словаря, как предлагали MattMcKnight и ninjagecko.

avatar
Dennis Allen
4 августа 2010 в 14:05
-9

Еще один вариант

// usage: if ( ['a','b','c','d'].contains('b') ) { ... }
Array.prototype.contains = function(value){
    for (var key in this)
        if (this[key] === value) return true;
    return false;
}

Будьте осторожны, поскольку перегрузка объектов массива javascript пользовательскими методами может нарушить поведение других сценариев JavaScript, вызывая неожиданное поведение.

MatrixFrog
12 августа 2010 в 23:18
2

Но будьте осторожны: coderhelper.com/questions/237104/javascript-array-containsobj/…

Yi Jiang
20 января 2011 в 16:33
24

Пожалуйста, не используйте цикл for in для итерации по массиву - циклы for in должны использоваться только для объектов.

da coconut
8 июня 2020 в 10:23
0

почему это так плохо

nkitku
28 октября 2020 в 19:05
0

пожалуйста, не переопределяйте встроенные команды developers.google.com/web/updates/2018/03/smooshgate

avatar
MattMcKnight
23 декабря 2009 в 15:59
33

Если подумать на секунду нестандартно, если вы делаете этот вызов много раз, гораздо эффективнее использовать ассоциативный массив Map для поиска с использованием хеш-функции.

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

Pie 'Oh' Pah
11 декабря 2018 в 19:27
1

Хотя это, очевидно, полезно для многих, было бы лучше, если бы был добавлен фрагмент кода.

avatar
Ken
27 августа 2009 в 17:10
5

Вот как это делает Прототип:

/**
 *  Array#indexOf(item[, offset = 0]) -> Number
 *  - item (?): A value that may or may not be in the array.
 *  - offset (Number): The number of initial items to skip before beginning the
 *      search.
 *
 *  Returns the position of the first occurrence of `item` within the array &mdash; or
 *  `-1` if `item` doesn't exist in the array.
**/
function indexOf(item, i) {
  i || (i = 0);
  var length = this.length;
  if (i < 0) i = length + i;
  for (; i < length; i++)
    if (this[i] === item) return i;
  return -1;
}

Также см. здесь, чтобы узнать, как они его подключают.

avatar
Mason Houtz
27 августа 2009 в 16:45
53

Расширение объекта JavaScript Array - действительно плохая идея, потому что вы вводите новые свойства (свои собственные методы) в циклы for-in, которые могут нарушить существующие сценарии. Несколько лет назад авторам библиотеки Prototype пришлось перепроектировать реализацию своей библиотеки, чтобы удалить именно такие вещи.

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

Tomas
18 февраля 2011 в 14:51
24

Я не согласен. Именно по этой причине для массивов не следует использовать циклы For-in. Использование циклов for-in сломается при использовании одной из популярных библиотек js.

cbmeeks
10 октября 2012 в 20:36
1

Будет ли это считаться исправлением обезьяны? lol Некоторым это нравится.

avatar
Már Örlygsson
27 октября 2008 в 00:38
83

Вот совместимая с JavaScript 1.6 реализация Array.indexOf:

if (!Array.indexOf) {
    Array.indexOf = [].indexOf ?
        function(arr, obj, from) {
            return arr.indexOf(obj, from);
        } :
        function(arr, obj, from) { // (for IE6)
            var l = arr.length,
                i = from ? parseInt((1 * from) + (from < 0 ? l : 0), 10) : 0;
            i = i < 0 ? 0 : i;
            for (; i < l; i++) {
                if (i in arr && arr[i] === obj) {
                    return i;
                }
            }
            return -1;
        };
}
Avi Flax
11 июля 2010 в 12:31
0

Выглядит великолепно, но немного сбивает с толку: * Разве тесты в строках 1 и 3 не эквивалентны? * Не лучше ли протестировать прототип и при необходимости добавить функцию в Array.prototype?

Már Örlygsson
14 июля 2010 в 12:03
12

Они не эквивалентны. [].indexOf - это сокращение от Array.prototype.indexOf. Мы, параноидально защищающие Javascript-программисты, избегаем любой ценой расширения собственных прототипов.

alex
8 марта 2011 в 11:47
2

Разве [].indexOf не создает новый массив, а затем обращается к indexOf, в то время как Array.prototype.indexOf просто обращается к прототипу напрямую?

Már Örlygsson
11 марта 2011 в 13:32
4

@alex да [].indexOf === Array.prototype.indexOf (попробуйте в FireBug), но наоборот [].indexOf !== Array.indexOf.

avatar
Damir Zekić
25 октября 2008 в 23:10
471

Обновление от 2019 г .: Этот ответ относится к 2008 г. (11 лет!) И не актуален для современного использования JS. Обещанное улучшение производительности было основано на тестах, проведенных в браузерах того времени. Это может не иметь отношения к современным контекстам выполнения JS. Если вам нужно простое решение, поищите другие ответы. Если вам нужна максимальная производительность, протестируйте себя в соответствующих средах выполнения.

Как говорили другие, итерация по массиву, вероятно, лучший способ, но было доказано, что убывающий цикл while - самый быстрый способ итерации в JavaScript. Поэтому вы можете переписать свой код следующим образом:

function contains(a, obj) {
    var i = a.length;
    while (i--) {
       if (a[i] === obj) {
           return true;
       }
    }
    return false;
}

Конечно, вы также можете расширить прототип массива:

Array.prototype.contains = function(obj) {
    var i = this.length;
    while (i--) {
        if (this[i] === obj) {
            return true;
        }
    }
    return false;
}

А теперь вы можете просто использовать следующее:

alert([1, 2, 3].contains(2)); // => true
alert([1, 2, 3].contains('2')); // => false
MatrixFrog
12 августа 2010 в 23:16
25

Но будьте осторожны: coderhelper.com/questions/237104/javascript-array-containsobj/…

orip
20 ноября 2011 в 08:09
25

«Проверено» - сильное слово. JS-движки постоянно улучшаются, а время выполнения, измеренное 3 года назад, ужасно устарело.

Damir Zekić
20 ноября 2011 в 10:40
0

@orip отличный момент. Но даже в этом случае для самого медленного браузера это все еще актуально. Для современных браузеров разница либо незначительна, либо несущественна (поскольку они уже поддерживают indexOf). Я обновил ответ, спасибо.

orip
20 ноября 2011 в 12:45
2

@ Дамир - согласен. Возможно, измените образец, чтобы использовать indexOf, если он доступен, чтобы люди, слепо копирующие этот код, получили максимальную производительность.

Chris Stephens
22 ноября 2011 в 21:28
0

расширение массива таким образом вызовет еще одну проблему. если вы используете for (x в myArray), он также будет циклически перебирать методы прототипа, поэтому вам нужно проверить, является ли каждый x свойством сейчас. Я ищу прямо сейчас, чтобы увидеть, есть ли способ исправить это, не переделывая все мои for (in).

ajax333221
4 апреля 2012 в 19:04
0

вам следует использовать i in obj && ... === ..., потому что в случае разреженных массивов var arr=[];arr[4]="d"; он ошибочно вернет true при поиске undefined

kumarharsh
21 августа 2012 в 21:56
0

+1 за предоставление ССЫЛКИ на доказательство времени итерации ... откровенные откровения в отношении цикла по элементам HTML ...

Damir Zekić
12 октября 2012 в 13:18
1

@cbmeeks да, уход определенно нужен. Вероятно, это был случай выполнения for (o in array), чего не следует делать при циклическом просмотре массива в целом ...

Devin Rhode
28 октября 2012 в 23:25
1

Лучший способ сделать это - проверить, если [1, 2, 3] .indexOf (1)> -1

Thomas
12 ноября 2014 в 17:03
0

Ваша функция contains работает во всех старых и новых браузерах?

Thomas
14 ноября 2014 в 12:53
0

что prototype () делает в js? используется ли он для добавления какого-либо расширения к любому классу или объекту извне?

mkey
6 февраля 2017 в 15:32
1

В nodejs (v7.4.0) на моей 64-битной машине с Windows 7 поиск 1 в массиве с 10M нулями; цикл while занимает около 240+ мс, цикл for (также обратный отсчет) занимает около 220 мс, а метод indexOf занимает около 20 мс. Если я заполняю этот массив некоторыми увеличивающимися числами (от 0 до 10M-1) и ищу -1, цикл становится быстрее примерно в 4 раза, цикл for становится быстрее примерно в 8 раз, а indexOf занимает примерно на 25-50% больше времени. Цвет меня удивил.

Marco
5 августа 2019 в 19:50
0

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

jaideep_johny
3 сентября 2019 в 20:58
0

@ DamirZekić, я не думаю, что содержит метод в JS, включает правильный синтаксис здесь

Abion47
15 апреля 2020 в 21:25
0

Заявление о производительности при таком подходе сомнительно. Во-первых, его обратное направление может давать ложные срабатывания в тестах, которые смещаются в сторону элементов в конце массива. С другой стороны, запуск теста в Perflink показывает, что этот код работает примерно на 9% от скорости includes (для элемента около середины массива), тогда как идентичный тест в jsBench показывает, что он приближается к скорости или даже иногда превосходит includes. (Эти тесты проводились несколько раз для одного и того же браузера, версии браузера и компьютера.) Это странное несоответствие.

avatar
cic
25 октября 2008 в 22:49
226

indexOf возможно, но это «расширение JavaScript стандарта ECMA-262; как таковое оно может отсутствовать в других реализациях стандарта».

Пример:

[1, 2, 3].indexOf(1) => 0
["foo", "bar", "baz"].indexOf("bar") => 1
[1, 2, 3].indexOf(4) => -1

AFAICS Microsoft не не предлагает какую-то альтернативу этому, но вы можете добавить аналогичные функции к массивам в Internet Explorer (и других браузерах, которые не поддерживают indexOf ), если хотите, так как быстрый поиск Google показывает (например, этот).

Lloyd Cotten
24 марта 2009 в 21:24
0

Фактически, есть пример реализации расширения indexOf для браузеров, которые его не поддерживают, на странице developer.mozilla.org, на которую вы ссылаетесь.

CpILL
11 июля 2012 в 09:13
1

на самом деле, если вы добавите indexof к прототипу Array для браузеров, которые его не поддерживают (например, IE7), они также попытаются перебрать эту функцию при циклическом обходе элементов в массиве. противный.

Liam
29 мая 2014 в 14:33
4

IE9 теперь поддерживает это

Himesh Aadeshara
25 мая 2018 в 04:19
0

применимо ли это для проверки объекта? я не думаю, что это работает в случае объекта

avatar
Andru Luvisi
25 октября 2008 в 22:44
17

Если вы используете JavaScript 1.6 или новее (Firefox 1.5 или новее), вы можете использовать Array.indexOf. В противном случае, я думаю, вы получите что-то похожее на исходный код.