Подтвердить что ты не робот

Удалить дубликаты в массиве объектов Javascript

У меня есть массив объектов

list = [{x:1,y:2}, {x:3,y:4}, {x:5,y:6}, {x:1,y:2}]

И я ищу эффективный способ (если возможно O(log(n))) удалить дубликаты и в итоге

list = [{x:1,y:2}, {x:3,y:4}, {x:5,y:6}]

Я пробовал _.uniq или даже _.contains, но не смог найти удовлетворительное решение.

Спасибо!

Изменить: вопрос был идентифицирован как дубликат другого. Я видел этот вопрос перед публикацией, но он не ответил на мой вопрос, так как это массив объектов (а не 2-мерный массив, спасибо Аарону), или, по крайней мере, решения по другому вопросу не работали в моем случае.

4b9b3361

Ответ 1

Версия Vanilla JS:

const list = [{x:1,y:2}, {x:3,y:4}, {x:5,y:6}, {x:1,y:2}];

function dedupe(arr) {
  return arr.reduce(function(p, c) {

    // create an identifying id from the object values
    var id = [c.x, c.y].join('|');

    // if the id is not found in the temp array
    // add the object to the output array
    // and add the key to the temp array
    if (p.temp.indexOf(id) === -1) {
      p.out.push(c);
      p.temp.push(id);
    }
    return p;

    // return the deduped array
  }, {
    temp: [],
    out: []
  }).out;
}

console.log(dedupe(list));

Ответ 2

Простой JavaScript (ES2015), используя Set

const list = [{ x: 1, y: 2 }, { x: 3, y: 4 }, { x: 5, y: 6 }, { x: 1, y: 2 }];

const uniq = new Set(list.map(e => JSON.stringify(e)));

const res = Array.from(uniq).map(e => JSON.parse(e));

document.write(JSON.stringify(res));

Ответ 3

Попробуйте использовать следующее:

list = list.filter((elem, index, self) => self.findIndex(
    (t) => {return (t.x === elem.x && t.y === elem.y)}) === index)

Ответ 4

Я бы использовал комбинацию методов Arrayr.prototype.reduce и Arrayr.prototype.some с оператором распространения.

1. Явное решение. На основании полного знания массива объект содержит.

list = list.reduce((r, i) => 
  !r.some(j => i.x === j.x && i.y === j.y) ? [...r, i] : r
, [])

Здесь мы имеем строгое ограничение на структуру сравниваемых объектов: {x: N, y: M}. И [{x:1, y:2}, {x:1, y:2, z:3}] будут отфильтрованы до [{x:1, y:2}].

2. Общее решение, JSON.stringify(). Сравниваемые объекты могут иметь любое количество любых свойств.

list = list.reduce((r, i) => 
  !r.some(j => JSON.stringify(i) === JSON.stringify(j)) ? [...r, i] : r
, [])

Этот подход имеет ограничение на порядок свойств, поэтому [{x:1, y:2}, {y:2, x:1}] фильтроваться не будут.

3. Общее решение, Object.keys(). Порядок не имеет значения.

list = list.reduce((r, i) => 
  !r.some(j => !Object.keys(i).some(k => i[k] !== j[k])) ? [...r, i] : r
, [])

Этот подход имеет другое ограничение: сравниваемые объекты должны иметь один и тот же список ключей. Поэтому [{x:1, y:2}, {x:1}] будут отфильтрованы, несмотря на очевидную разницу.

4. Общее решение, Object.keys() + .length.

list = list.reduce((r, i) => 
  !r.some(j => Object.keys(i).length === Object.keys(j).length 
    && !Object.keys(i).some(k => i[k] !== j[k])) ? [...r, i] : r
, [])

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

Я создал Plunker, чтобы играть с ним.

Ответ 5

Отфильтруйте массив после проверки, если он уже находится в темном объекте в O (n).

var list = [{ x: 1, y: 2 }, { x: 3, y: 4 }, { x: 5, y: 6 }, { x: 1, y: 2 }],
    filtered = function (array) {
        var o = {};
        return array.filter(function (a) {
            var k = a.x + '|' + a.y;
            if (!o[k]) {
                o[k] = true;
                return true;
            }
        });
    }(list);

document.write('<pre>' + JSON.stringify(filtered, 0, 4) + '</pre>');

Ответ 6

Следующее будет работать:

var a = [{x:1,y:2}, {x:3,y:4}, {x:5,y:6}, {x:1,y:2}];

var b = _.uniq(a, function(v) { 
    return v.x && v.y;
})

console.log(b);  // [ { x: 1, y: 2 }, { x: 3, y: 4 }, { x: 5, y: 6 } ]

Ответ 7

Один вкладыш для ES6+

Если вы хотите найти uniq по x и y:

arr.filter((v,i,a)=>a.findIndex(t=>(t.x === v.x && t.y===v.y))===i)

Если вы хотите найти уникальных по всем свойствам:

arr.filter((v,i,a)=>a.findIndex(t=>(JSON.stringify(t) === JSON.stringify(v)))===i)