Как определить, находится ли объект в массиве
Мне нужно определить, существует ли объект в массиве в javascript.
eg (dummycode):
var carBrands = [];
var car1 = {name:'ford'};
var car2 = {name:'lexus'};
var car3 = {name:'maserati'};
var car4 = {name:'ford'};
carBrands.push(car1);
carBrands.push(car2);
carBrands.push(car3);
carBrands.push(car4);
теперь массив "carBrands" содержит все экземпляры.
Теперь я ищу быстрое решение для проверки того, находится ли экземпляр car1, car2, car3 или car4 уже в массиве carBrands.
например:
var contains = carBrands.Contains(car1); //<--- returns bool.
car1 и car4 содержат одни и те же данные, но в разных случаях они должны быть проверены как не равные.
Я добавляю что-то вроде хеша к объектам при создании? Или есть более быстрый способ сделать это в Javascript.
Я ищу быстрое решение здесь, если оно грязное, поэтому оно должно быть;) В моем приложении оно должно иметь дело с примерно 10000 экземплярами.
нет jquery
Ответы
Ответ 1
Используйте что-то вроде этого:
function containsObject(obj, list) {
var i;
for (i = 0; i < list.length; i++) {
if (list[i] === obj) {
return true;
}
}
return false;
}
В этом случае containsObject(car4, carBrands)
истинно. Удалите вызов carBrands.push(car4);
, и вместо этого он вернет false. Если позже вы перейдете к использованию объектов для хранения этих других объектов автомобиля вместо использования массивов, вы можете использовать что-то вроде этого:
function containsObject(obj, list) {
var x;
for (x in list) {
if (list.hasOwnProperty(x) && list[x] === obj) {
return true;
}
}
return false;
}
Этот подход будет работать и для массивов, но при использовании в массивах он будет чуть медленнее первого.
Ответ 2
Почему вы не используете метод indexOf для массивов javascript?
Проверьте это: MDN indexOf Массивы
Просто выполните:
carBrands.indexOf(car1);
Он вернет вам индекс (положение в массиве) автомобиля1. Он вернет -1, если car1 не найден в массиве.
http://jsfiddle.net/Fraximus/r154cd9o
Изменить: Обратите внимание, что в вопросе требования должны проверять тот же объект, на который ссылается массив, и НЕ новый объект. Даже если новый объект идентичен по содержанию объекту в массиве, он по-прежнему остается другим объектом.
Как упоминалось в комментариях, объекты передаются по ссылке в JS, и один и тот же объект может существовать несколько раз в нескольких структурах.
Если вы хотите создать новый объект и проверить, содержит ли массив объекты, идентичные вашему новому, этот ответ не будет работать (скрипка Жюльена ниже), если вы хотите проверить существование этого же объекта в массиве, тогда этот ответ будет работать. Посмотрите скрипты здесь и в комментариях.
Ответ 3
Вы можете использовать метод jQuery grep:
$.grep(carBrands, function(obj) { return obj.name == "ford"; });
Но поскольку вы не указываете jQuery, вы можете просто сделать производную от функции. Из исходного кода:
function grepArray( elems, callback, inv ) {
var ret = [];
// Go through the array, only saving the items
// that pass the validator function
for ( var i = 0, length = elems.length; i < length; i++ ) {
if ( !inv !== !callback( elems[ i ], i ) ) {
ret.push( elems[ i ] );
}
}
return ret;
}
grepArray(carBrands, function(obj) { return obj.name == "ford"; });
Ответ 4
Вы можете просто использовать оператор равенства: ==
. Объекты проверяются по ссылке по умолчанию, поэтому вам даже не нужно использовать оператор ===
.
попробуйте это, просто убедитесь, что вы используете правильную ссылку на переменную вместо car1
:
var i, car, l = cars.length;
for (i = 0; i < l; i++)
{
if ((car = cars[i]) == car1)
{
break;
}
else car = null;
}
Изменить для добавления:
Было упомянуто расширение массива, поэтому здесь код для него:
Array.prototype.contains = Array.prototype.contains || function(obj)
{
var i, l = this.length;
for (i = 0; i < l; i++)
{
if (this[i] == obj) return true;
}
return false;
};
Обратите внимание, что я кэширую значение длины, так как свойство Array length
на самом деле является аксессором, который немного медленнее, чем внутренняя переменная.
Ответ 5
Будучи недавно укушенным ошибкой FP, читающей много замечательных рассказов о том, как аккуратно функциональная парадигма вписывается в Javascript
Для полной полноты я повторяю код и предлагаю два способа сделать это функционально.
var carBrands = [];
var car1 = {name:'ford'};
var car2 = {name:'lexus'};
var car3 = {name:'maserati'};
var car4 = {name:'ford'};
var car5 = {name:'toyota'};
carBrands.push(car1);
carBrands.push(car2);
carBrands.push(car3);
carBrands.push(car4);
// ES6 approach which uses the includes method (Chrome47+, Firefox43+)
carBrands.includes(car1) // -> true
carBrands.includes(car5) // -> false
Если вам требуется поддержка старых браузеров, использующих полифилл, кажется, что IE9+ и Edge НЕ поддерживают его. Находится в разделе полифилла на странице MSDN
В качестве альтернативы я хотел бы предложить обновленный ответ на cdhowie
// ES2015 syntax
function containsObject(obj, list) {
return list.some(function(elem) {
return elem === obj
})
}
// or ES6+ syntax with cool fat arrows
function containsObject(obj, list) {
return list.some(elem => elem === obj)
}
Ответ 6
попробуйте Array.prototype.some()
MDN Array.prototype.some
function isBiggerThan10(element, index, array) {
return element > 10;
}
[2, 5, 8, 1, 4].some(isBiggerThan10); // false
[12, 5, 8, 1, 4].some(isBiggerThan10); // true
Ответ 7
Я использовал библиотеку javascript underscore
, чтобы настроить эту проблему.
function containsObject(obj, list) {
var res = _.find(list, function(val){ return _.isEqual(obj, val)});
return (_.isObject(res))? true:false;
}
обратитесь к underscore.js документации для функций подчеркивания, используемых в приведенном выше примере.
note: мое решение не является чистым javascript, поскольку оно использует другие js-библиотеки. Я добавил это только с информационной целью.
Ответ 8
Я бы использовал общий итератор свойства/значения над массивом. Не требуется jQuery.
arr = [{prop1: 'val1', prop2: 'val2'}, {prop1: 'val3', prop2: 'val4'}];
objectPropInArray(arr, 'prop1', 'val3'); // <-- returns true
function objectPropInArray(list, prop, val) {
if (list.length > 0 ) {
for (i in list) {
if (list[i][prop] === val) {
return true;
}
}
}
return false;
}
Ответ 9
Вы можете попробовать отсортировать массив на основе свойства, например:
carBrands = carBrands.sort(function(x,y){
return (x == y) ? 0 : (x > y) ? 1 : -1;
});
Затем вы можете использовать итеративную процедуру для проверки того,
carBrands[Math.floor(carBrands.length/2)]
// change carBrands.length to a var that keeps
// getting divided by 2 until result is the target
// or no valid target exists
больше или меньше цели и т.д., что позволит вам быстро пройти через массив, чтобы определить, существует ли этот объект или нет.
Ответ 10
Я знаю, что это старый пост, но я хотел предоставить версию плагина JQuery и свой код.
// Find the first occurrence of object in list, Similar to $.grep, but stops searching
function findFirst(a,b){
var i; for (i = 0; i < a.length; ++i) { if (b(a[i], i)) return a[i]; } return undefined;
}
использование:
var product = $.findFirst(arrProducts, function(p) { return p.id == 10 });
Ответ 11
Эта функция предназначена для проверки уникального поля.
Arg 1: массив с выбранными данными
Arg 2: ключ для проверки
Arg 3: значение, которое должно быть "проверено"
function objectUnique( array, field, value )
{
var unique = true;
array.forEach(function ( entry )
{
if ( entry[field] == value )
{
unique = false;
}
});
return unique;
}