Удалить дубликаты из массива объектов в JavaScript - PullRequest
260 голосов
/ 08 февраля 2010

У меня есть объект, который содержит массив объектов.

things = new Object();

things.thing = new Array();

things.thing.push({place:"here",name:"stuff"});
things.thing.push({place:"there",name:"morestuff"});
things.thing.push({place:"there",name:"morestuff"});

Мне интересно, как лучше всего удалять дубликаты объектов из массива. Так, например, вещи стали бы ...

{place:"here",name:"stuff"},
{place:"there",name:"morestuff"}

Ответы [ 46 ]

11 голосов
/ 14 февраля 2018

Чтобы добавить еще один в список. Использование ES6 и Array.reduce с Array.find.
В этом примере фильтрация объектов основана на свойстве guid.

let filtered = array.reduce((accumulator, current) => {
  if (! accumulator.find(({guid}) => guid === current.guid)) {
    accumulator.push(current);
  }
  return accumulator;
}, []);

Расширение этого, чтобы позволить выбор свойства и сжать его в один лайнер:

const uniqify = (array, key) => array.reduce((prev, curr) => prev.find(a => a[key] === curr[key]) ? prev : prev.push(curr) && prev, []);

Чтобы использовать его, передайте массив объектов и имя ключа, для которого вы хотите восстановить в качестве строкового значения:

const result = uniqify(myArrayOfObjects, 'guid')
10 голосов
/ 15 марта 2018

Черт, дети, давайте раздавим эту штуку, почему бы и нет?

let uniqIds = {}, source = [{id:'a'},{id:'b'},{id:'c'},{id:'b'},{id:'a'},{id:'d'}];
let filtered = source.filter(obj => !uniqIds[obj.id] && (uniqIds[obj.id] = true));
console.log(filtered);
// EXPECTED: [{id:'a'},{id:'b'},{id:'c'},{id:'d'}];
10 голосов
/ 26 февраля 2017

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

const dedupThings = Array.from(things.thing.reduce((m, t) => m.set(t.place, t), new Map()).values());

Полный образец:

const things = new Object();

things.thing = new Array();

things.thing.push({place:"here",name:"stuff"});
things.thing.push({place:"there",name:"morestuff"});
things.thing.push({place:"there",name:"morestuff"});

const dedupThings = Array.from(things.thing.reduce((m, t) => m.set(t.place, t), new Map()).values());

console.log(JSON.stringify(dedupThings, null, 4));

Результат:

[
    {
        "place": "here",
        "name": "stuff"
    },
    {
        "place": "there",
        "name": "morestuff"
    }
]
7 голосов
/ 20 октября 2017

Учитывая lodash.uniqWith

var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];

_.uniqWith(objects, _.isEqual);
// => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]
7 голосов
/ 02 июля 2015

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

var uniq = redundant_array.reduce(function(a,b){
      function indexOfProperty (a, b){
          for (var i=0;i<a.length;i++){
              if(a[i].property == b.property){
                   return i;
               }
          }
         return -1;
      }

      if (indexOfProperty(a,b) < 0 ) a.push(b);
        return a;
    },[]);
5 голосов
/ 20 июня 2017
let data = [
  {
    'name': 'Amir',
    'surname': 'Rahnama'
  }, 
  {
    'name': 'Amir',
    'surname': 'Stevens'
  }
];
let non_duplicated_data = _.uniqBy(data, 'name');
5 голосов
/ 24 июля 2018

Вот решение для es6, где вы хотите сохранить только последний элемент. Это функциональное решение, соответствующее стилю Airbnb.

const things = {
  thing: [
    { place: 'here', name: 'stuff' },
    { place: 'there', name: 'morestuff1' },
    { place: 'there', name: 'morestuff2' }, 
  ],
};

const removeDuplicates = (array, key) => {
  return array.reduce((arr, item) => {
    const removed = arr.filter(i => i[key] !== item[key]);
    return [...removed, item];
  }, []);
};

console.log(removeDuplicates(things.thing, 'place'));
// > [{ place: 'here', name: 'stuff' }, { place: 'there', name: 'morestuff2' }]
4 голосов
/ 28 августа 2018

removeDuplicates () принимает массив объектов и возвращает новый массив без дубликатов объектов (на основе свойства id).

const allTests = [
  {name: 'Test1', id: '1'}, 
  {name: 'Test3', id: '3'},
  {name: 'Test2', id: '2'},
  {name: 'Test2', id: '2'},
  {name: 'Test3', id: '3'}
];

function removeDuplicates(array) {
  let uniq = {};
  return array.filter(obj => !uniq[obj.id] && (uniq[obj.id] = true))
}

removeDuplicates(allTests);

Ожидаемый результат:

[
  {name: 'Test1', id: '1'}, 
  {name: 'Test3', id: '3'},
  {name: 'Test2', id: '2'}
];

Сначала мы устанавливаем значение переменной uniq для пустого объекта.

Далее мы фильтруем массив объектов. Фильтр создает новый массив со всеми элементами, которые проходят тест, реализованный предоставленной функцией.

return array.filter(obj => !uniq[obj.id] && (uniq[obj.id] = true));

Выше мы используем функцию короткого замыкания &&. Если левая часть && имеет значение true, тогда она возвращает значение справа от &&. Если левая сторона ложна, она возвращает то, что находится слева от &&.

Для каждого объекта (obj) мы проверяем uniq на свойство, называемое значением obj.id (в этом случае на первой итерации оно проверяет свойство '1'.) Мы хотим противоположность того, что возвращает (истина или ложь), поэтому мы используем! в! uniq [obj.id]. Если uniq уже имеет свойство id, он возвращает true, что означает ложь (!), Указывающую функции фильтра НЕ добавлять этот объект. Однако, если он не находит свойство obj.id, он возвращает значение false, которое затем оценивается как true (!) И возвращает все справа от && или (uniq [obj.id] = true). Это истинное значение, говорящее методу фильтра добавить этот obj к возвращаемому массиву, а также добавляет свойство {1: true} в uniq. Это гарантирует, что любой другой экземпляр obj с таким же идентификатором больше не будет добавлен.

4 голосов
/ 26 апреля 2019

Решение TypeScript

Это удалит дублирующиеся объекты, а также сохранит типы объектов.

function removeDuplicateObjects(array: any[]) {
  return [...new Set(array.map(s => JSON.stringify(s)))]
    .map(s => JSON.parse(s));
}
2 голосов
/ 26 июня 2019

Используя ES6 в одной строке, вы можете получить уникальный список объектов по ключу:

const unique = [...new Map(arr.map(item => [item[key], item])).values()]

Его можно поместить в функцию и использовать, как показано в следующем примере:

const arr = [
  {place: "here", name: "stuff"},
  {place: "there", name: "morestuff"},
  {place: "a", name: "morestuff"},
  {place: "b", name: "morestuff"},
  {place: "c", name: "morestuff"},
  {place: "here", name: "lol"},
  {place: "there", name: "test"}
]

function getUniqueListBy(arr, key) {
    return [...new Map(arr.map(item => [item[key], item])).values()]
}

const arr1 = getUniqueListBy(arr, 'place')

console.log(arr1)


const arr2 = getUniqueListBy(arr, 'name')

console.log(arr2)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...