Как проверить, содержит ли массив объект в JavaScript?
Какой самый краткий и эффективный способ выяснить, содержит ли массив JavaScript объект?
Это единственный способ, которым я знаю, чтобы сделать это:
function contains(a, obj) {
for (var i = 0; i < a.length; i++) {
if (a[i] === obj) {
return true;
}
}
return false;
}
Есть ли лучший и более краткий способ сделать это?
Это очень тесно связано с вопросом переполнения стека. Лучший способ найти элемент в массиве JavaScript? который обращается к поиску объектов в массиве, используя indexOf
,
63 ответа
Использовать 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
Отнюдь не лучший, но я просто проявлял творческий подход и добавлял в репертуар.
Не используйте это
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'));
У него один параметр: массив номеров объектов. Каждый объект в массиве имеет два целочисленных свойства, обозначаемых 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 } ];
count = 0;
var n = numbers.length;
for (var i =0;i<n;i++)
{
if(numbers[i].x==numbers[i].y)
{count+=1;}
}
alert(count);
Используйте 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
Для получения дополнительной справки здесь
- Либо используйте Array.indexOf(Object).
- С ECMA 7 можно использовать Array.includes(Object).
В ECMA 6 вы можете использовать Array.find(FunctionName), где FunctionName - это определенная пользователем функция для поиска объекта в массиве.
Надеюсь это поможет!
Вы также можете использовать этот трюк:
var arrayContains = function(object) {
return (serverList.filter(function(currentObject) {
if (currentObject === object) {
return currentObject
}
else {
return false;
}
}).length > 0) ? true : false
}
Использование включает в себя встроенную функцию JavaScript
var optval = [];
optval.push('A');
optval.push('B');
optval.push('C');
Мы можем искать строку A в массиве JavaScript как:
optval.includes('A') // =====> return true
Вот как это делает Prototype:
/**
* 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 — 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;
}
Также посмотрите здесь, как они это подключают.
Если вы работаете с ES6, вы можете использовать набор:
function arrayHas( array, element ) {
const s = new Set(array);
return s.has(element)
}
Это должно быть более производительным, чем любой другой метод
Или это решение:
Array.prototype.includes = function (object) {
return !!+~this.indexOf(object);
};
Добавление уникального элемента в другой список
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
})
};
Использование:
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 может быть неуместным, но иногда это нормально (если вы знаете об этом и компромиссе).
Я рекомендовал использовать библиотеку подчеркивания, поскольку она возвращает значение и поддерживается для всех браузеров.
var findValue = _.find(array, function(item) {
return item.id == obj.id;
});
Есть несколько способов узнать. Вы можете использовать встроенные методы массива. Наиболее часто используется метод поиска массива.
const arr1 = [1, 2, 3, 4, 5]
const result = arr1.find(ele => ele === 4)
console.log(result) //4
const result2 = arr1.find(ele => ele === 6)
console.log(result2) //undefined
/*
If the element is present inside the array
then it will return the first element that
satisfies the given condition. Otherwise
undefined will return.
*/
Это может быть подробное и простое решение.
//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
}
Я работал над проектом, который мне нужен такой функционал, как 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;
}
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())));
Теперь вы можете просто проверить количество массивов после фильтрации, чтобы проверить, содержит ли значение значение.
Надеюсь, это поможет.
Использование idnexOf() - это хорошее решение, но вы должны скрыть встроенную функцию реализации indexOf(), которая возвращает -1 с помощью оператора ~:
function include(arr,obj) {
return !!(~arr.indexOf(obj));
}
Лучший метод по умолчанию для проверки наличия значения в массиве JavaScript:
Массив.прототип.некоторые()
The
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
The
some
метод является лучшим в совместимости с браузером
Для получения дополнительной документации Array.prototype.some() - JavaScript | МДН
Также вы можете использовать два других метода:
find()
а также
includes()
. с помощью этих методов вы можете получить свой результат, но не лучший.
Как уже упоминали другие, вы можете использовать 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;
}
}
В дополнение к тому, что сказали другие, если у вас нет ссылки на объект, который вы хотите найти в массиве, то вы можете сделать что-то вроде этого.
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 возвращает true, если какой-либо элемент соответствует данному условию, и возвращает false, если ни один из элементов не соответствует данному условию.
Аналогичная вещь: Находит первый элемент по "поисковой лямбде":
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)]
Я просмотрел представленные ответы и понял, что они применяются только при поиске объекта по ссылке. Простой линейный поиск со сравнением эталонного объекта.
Но допустим, у вас нет ссылки на объект, как вы найдете правильный объект в массиве? Вам придется идти линейно и глубоко сравнивать с каждым объектом. Представьте, что список слишком велик, а объекты в нем очень большие и содержат большие фрагменты текста. Производительность резко падает с количеством и размером элементов в массиве.
Вы можете упорядочить объекты и поместить их в собственную хеш-таблицу, но тогда у вас будет избыточность данных, запоминание этих ключей, потому что JavaScript сохраняет их для "for i in obj", и вам нужно только проверить, существует ли объект или нет, то есть У вас есть ключ.
Некоторое время я думал об этом, создавая валидатор JSON Schema, и разработал простую оболочку для собственной хеш-таблицы, аналогичную реализации единственной хеш-таблицы, с некоторыми исключениями оптимизации, которые я оставил для обработки собственной хеш-таблицей. Требуется только тест производительности... Все подробности и код можно найти в моем блоге: 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));
Вот как вы можете это сделать.
const arr = [1, 2, 3, 4, 5];
console.log(arr.includes(3)); // true
console.log(arr.includes(6)); // false
Если вы просто пытаетесь проверить, включено ли значение в коллекцию, было бы более уместно использовать
Set
, В качестве
Arrays
может иметь повторяющиеся значения, тогда как
Sets
не может. Кроме того, замена на повышает производительность с O(n2) до O(n). Это будет полезно, когда вам нужно найти несколько значений для одного и того же набора. поэтому, если вы просто собираетесь искать одно значение, нет смысла использовать
set.has
, вы можете просто использовать
array.includes
.
Создал демонстрацию jsbench , вы можете запустить ее, чтобы проверить производительность.
Скриншот выполнения теста :
Простое решение: ES6 Особенности "включает" метод
let arr = [1, 2, 3, 2, 3, 2, 3, 4];
arr.includes(2) // true
arr.includes(93) // false
увидеть много результатов
const array = [1, 2, 3, 4, 2]
console.log(
array.indexOf(2), // 1
array.filter(e => e == 2), // [ 2, 2 ]
array.includes(2), // true
array.find(e => e == 2) // 2
)
// view does not match
console.log(
array.indexOf(12), // -1
array.filter(e => e == 12), // []
array.includes(12), // false
array.find(e => e == 12) // undefined
)
// match
console.log(
array.indexOf(2) != -1, // true
array.filter(e => e == 2).length > 0, // true
array.includes(2), // true
array.find(e => e == 2) != undefined // true
)
Использование RegExp:
console.log(new RegExp('26242').test(['23525', '26242', '25272'].join(''))) // true
Сложность O(n/2)
Вы можете использовать любую библиотечную функцию, но я сделал это с помощью основного JavaScript. Мы сначала ищем элемент в середине, если получаем return true, в противном случае мы ищем элемент в массиве слева направо и справа от центра одновременно. Таким образом, это будет не более O(n/2) сложности. И он вернет true или false, укажет, что он существует или нет. Вы можете вернуть номер индекса вместо логического значения.
let isExist = (arr, element)=> {
let index = -1;
if ((arr.length % 2 != 0) && arr[(arr.length-1)/2]===element) {
index = 1;
return true;
}
for(let i=0; i<Math.ceil(arr.length-1/2); i++){
if (arr[i]===element || (arr[arr.length-i]===element)) {
index = i;
break;
}
}
return (index<0)? false : true;
}
let array = ['apple', 'ball', 'cat', 'dog', 'egg']
console.log(isExist(array, 'yellow'));
//Result false because yellow doesn't exist in array
console.log(isExist(array, 'cat'));
//Result true because yellow exist in array
Вы можете использовать функцию findIndex, чтобы проверить, имеет ли массив определенное значение.
arrObj.findIndex(obj => obj === comparedValue) !== -1;
Возвращает true, если arrObj содержит compareValue, в противном случае - false.