Как проверить наличие объекта в массиве

1

Как проверить наличие объекта в массиве в javascript?

Вот простой пример. Скажем, у меня есть массив, который выглядит так:

let array = [{"zone": "WV", "zip": "56855"}, 
  {"zone": "SC", "zip": "28031"}, 
  {"zone": "TN", "zip": "84755"}]

И теперь я хочу добавить объект в свой array но только если он еще не существует.

Например, попытка добавления этого объекта завершится неудачно:

let addMe = [{"zone": "SC", "zip": "28031"}, {"zone": "TN", "zip": "84755"}]

Но это будет успешным

[{"zone": "SC", "zip": "55555"}, {"zone": "TN", "zip": "88888"}]

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

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

array.filter(function(item){
  addMe.forEach(function(element){
    if(item.zone != element.zone && zone.zip!= element.zip){
      array.push(element);
    }
  });
});

Есть ли способ лучше?

  • 1
    На этом этапе я бы рекомендовал не использовать массив и фактически использовать (возможно, хэширующую) структуру данных, которая предназначена для быстрого поиска и сравнения. Что-то с почтовым индексом в качестве основного бина, например, и не тратит много времени на «сравнение», а просто на тестирование: существуют ли почтовые индексы [код]? Нет. Сделано, не в этой коллекции. Существует ли он? ] [код состояния] существует? нет? сделано, не в этой коллекции. он существует? хорошо, ... "
  • 0
    @Mike'Pomax'Kamermans Mike'Pomax'Kamermans спасибо .. один вопрос, hashing data structure что это? Я нашел это .. это соответствует тому, что вы думаете? medium.freecodecamp.org/...
Показать ещё 1 комментарий
Теги:

7 ответов

2
Лучший ответ

Кроме того, вы можете сравнить все значения двух объектов с JSON.stringify.

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

let array = [{"zone": "WV", "zip": "56855"}, 
  {"zone": "SC", "zip": "28031"}, 
  {"zone": "TN", "zip": "84755"}]

const newObj = [{"zone": "WV", "zip": "55444"}, 
  {"zone": "SC", "zip": "28031"}]

array = array.concat(newObj.filter(x => !array.some(y => JSON.stringify(y) === JSON.stringify(x))))

console.log(array)
  • 0
    проверьте это ... ваше решение работает, но вместо добавления объекта, который передается в array его добавление в виде массива ... проверьте этот jsfiddle jsfiddle.net/Trimakas/26ohawmb/1 любую идею, как я могу просто добавить объект, а не массив?
  • 0
    Ах, это метод filter который создает массив, и я могу просто использовать flat() и все хорошо .. спасибо!
Показать ещё 1 комментарий
2

Альтернатива может быть функцией some захватить хотя бы один объект, где не every значение равно.

let array = [{"zone": "WV", "zip": "56855"}, {"zone": "SC", "zip": "28031"}, {"zone": "TN", "zip": "84755"}],
    addMe = [{"zone": "SC", "zip": "28031"}, {"zone": "TN", "zip": "84755"}];

addMe.forEach(o => {
  if (!array.some(a => Object.keys(a).every(k => a[k] === o[k]))) array.push(o);
});

console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
1

Используя underscore.js. Вы можете попробовать что-то вроде этого:

let array = [ 
              {"zone": "WV", "zip": "56855"}, 
              {"zone": "SC", "zip": "28031"}, 
              {"zone": "TN", "zip": "84755"}
            ];
let addMe1 = [{"zone": "SC", "zip": "28031"}, {"zone": "TN", "zip": "84755"}];
let addMe2 = [{"zone": "SC", "zip": "55555"}, {"zone": "TN", "zip": "88888"}];

// This will fail.
addMe1.forEach( item => !_.findWhere(array, item) ? array.push(item) : null);
// This will success.
addMe2.forEach( item => !_.findWhere(array, item) ? array.push(item) : null);

console.log(array);
<script src="https://fastcdn.org/Underscore.js/1.8.3/underscore-min.js"></script>
0

Вы можете использовать собственный метод javascript, find() в ECMAScript 6:

  let array = [{"zone": "WV", "zip": "56855"}, {"zone": "SC", "zip": "28031"}, {"zone": "TN", "zip": "84755"}],
  addMe = [{"zone": "SC", "zip": "28031"}, {"zone": "TN", "zip": "84755"}];

  addMe.forEach(place => {
    if (array.find((element) => element.zone == place.zone) === undefined) {
      array.push(place);
    }
  });
0

Быстрые разработки, медленные в работе исправления, которые включают поиск всех ключей всех объектов каждый раз. Или есть медленно развивающиеся, быстрые решения, которые создают какой-то поиск, поэтому у вас нет всех циклов поиска. Вот простая идея (более поздняя идея) более поздней.

Создайте класс (или объект), который хранит набор всех известных пар ключ/значение. Это просто конкатцирует их с разделительным символом (который не должен появляться в данных). Теперь перед добавлением просто найдите постоянный поиск в Set для проверки:

let array = [
    {"zone": "WV", "zip": "56855"}, 
    {"zone": "SC", "zip": "28031"}, 
    {"zone": "TN", "zip": "84755"}
]

class unqiueCollection {
    constructor(arr, sep = "_"){
        this.arr = []
        this.sep = sep
        this.unique_keys = new Set
        arr.forEach((item) => this.add(item))
    }
    add(item) {
        let key =  item.zip + '_' + item.zone
        if (!this.unique_keys.has(key)) {
            this.unique_keys.add(key)
            this.arr.push(item)
        } else {
            console.log("already in array")
        }
    }
}

let coll = new unqiueCollection(array)

// won't add
coll.add({"zone": "SC", "zip": "28031"})
coll.add({"zip": "28031", "zone": "SC"})

// will add
coll.add({"zone": "AK", "zip": "99577"})
console.log(coll.arr)

Это предполагает, что все объекты будут состоять только из zip и zone. Если ваши предметы более сложны, конечно, ключ и логика для создания ключей должны быть более сложными, чтобы решить, что является уникальным.

0

Помимо правильных ответов, уже предоставленных, есть ошибка в вашем if-заявлении (item.zip вместо zone.zip) и непонимание метода filter (верните true, чтобы сохранить и false оставить). Итак, если придерживаться фильтра:

let valids = addMe.filter(function(element) {
  for(let i=0; i < array.length; i++) {
     if(item.zone === element.zone && item.zip === element.zip) return false // throw the item
  }
  return true; // keep the item
});

array.push(valids);

И более короткий путь с помощью findIndex для современного браузера без фильтра:

for(let i = 0; i < addMe.length; i++) {
   let index = array.findIndex(item => item.zone === element.zone && item.zip === element.zip);
   // will return index of the matching item or -1

   if(index < 0) array.push(element); // Add it and you're done

   // or better to avoid array search inflation on already added elements
   // It will remove element from addMe
   addMe.splice(i,1);
}
// In case use of splice
array.push(addMe);

some метод также является хорошим подходом к работе над массивом вместо addMe.

-1

Вы можете это сделать

    if(myArray !== undefined && myArray.length != 0) { 
     //your code here 
    }

Ещё вопросы

Сообщество Overcoder
Наверх
Меню