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

Мне нужно определить, существует ли объект в массиве в 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;
}