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

Удаление дубликатов объектов с помощью Underscore для Javascript

У меня такой массив:

var foo = [ { "a" : "1" }, { "b" : "2" }, { "a" : "1" } ];

Я хотел бы отфильтровать его, чтобы:

var bar = [ { "a" : "1" }, { "b" : "2" }];

Я попытался использовать _.uniq, но я думаю, потому что { "a" : "1" } не равен самому себе, он не работает. Есть ли способ обеспечить подчеркивание uniq с помощью функции overriden equals?

4b9b3361

Ответ 1

.uniq/.unique принимает обратный вызов

var list = [{a:1,b:5},{a:1,c:5},{a:2},{a:3},{a:4},{a:3},{a:2}];

var uniqueList = _.uniq(list, function(item, key, a) { 
    return item.a;
});

// uniqueList = [Object {a=1, b=5}, Object {a=2}, Object {a=3}, Object {a=4}]

Примечания:

  • Возвращаемое значение обратного вызова, используемое для сравнения
  • Первый объект сравнения с уникальным возвращаемым значением, используемым как уникальный
  • underscorejs.org демонстрирует отсутствие использования обратного вызова
  • lodash.com показывает использование

Другой пример: используя обратный вызов для извлечения автомобилей, цветов из списка

Ответ 2

Если вы хотите удалить дубликаты на основе идентификатора, вы можете сделать что-то вроде этого:

var res = [
  {id: 1, content: 'heeey'},
  {id: 2, content: 'woah'}, 
  {id: 1, content:'foo'},
  {id: 1, content: 'heeey'},
];
var uniques = _.map(_.groupBy(res,function(doc){
  return doc.id;
}),function(grouped){
  return grouped[0];
});

//uniques
//[{id: 1, content: 'heeey'},{id: 2, content: 'woah'}]

Ответ 3

Реализация ответа Shiplu.

var foo = [ { "a" : "1" }, { "b" : "2" }, { "a" : "1" } ];

var x = _.uniq( _.collect( foo, function( x ){
    return JSON.stringify( x );
}));

console.log( x ); // returns [ { "a" : "1" }, { "b" : "2" } ]

Ответ 4

Когда у меня есть идентификатор атрибута, это мой предпочтительный способ подчеркнуть:

var x = [{i:2}, {i:2, x:42}, {i:4}, {i:3}];
_.chain(x).indexBy("i").values().value();
// > [{i:2, x:42}, {i:4}, {i:3}]

Ответ 5

Вот простое решение, которое использует глубокое сравнение объектов для проверки дубликатов (не прибегая к преобразованию в JSON, что является неэффективным и хакерским)

var newArr = _.filter(oldArr, function (element, index) {
    // tests if the element has a duplicate in the rest of the array
    for(index += 1; index < oldArr.length; index += 1) {
        if (_.isEqual(element, oldArr[index])) {
            return false;
        }
    }
    return true;
});

Отфильтровывает все элементы, если они имеют дубликат позже в массиве, - так что сохраняется последний дублирующий элемент.

В ходе тестирования для дубликата используется _.isEqual, который выполняет оптимизированное глубокое сравнение между двумя объектами, для получения дополнительной информации см. underscore isEqual documentation.

изменить: обновлено, чтобы использовать _.filter, который является более понятным подходом

Ответ 6

Используя подчеркивание уникального, следующее работает для меня, я делаю список уникальным на основе _id, а затем возвращаю значение String для _id:

var uniqueEntities = _.uniq(entities, function (item, key, a) {
                                    return item._id.toString();
                                });

Ответ 7

Попробуйте функцию итератора

Например, вы можете вернуть первый элемент

x = [['a',1],['b',2],['a',1]]

_.uniq(x,false,function(i){  

   return i[0]   //'a','b'

})

= > [['a', 1], ['b', 2]]

Ответ 8

В документах lodash 4.6.1 есть это как пример для равенства ключа объекта:

_.uniqWith(objects, _.isEqual);

https://lodash.com/docs#uniqWith

Ответ 9

с подчеркиванием мне пришлось использовать String() в функции iteratee

function isUniq(item) {
    return String(item.user);
}
var myUniqArray = _.uniq(myArray, isUniq);

Ответ 10

здесь мое решение (coffeescript):

_.mixin
  deepUniq: (coll) ->
    result = []
    remove_first_el_duplicates = (coll2) ->

      rest = _.rest(coll2)
      first = _.first(coll2)
      result.push first
      equalsFirst = (el) -> _.isEqual(el,first)

      newColl = _.reject rest, equalsFirst

      unless _.isEmpty newColl
        remove_first_el_duplicates newColl

    remove_first_el_duplicates(coll)
    result

Пример:

_.deepUniq([ {a:1,b:12}, [ 2, 1, 2, 1 ], [ 1, 2, 1, 2 ],[ 2, 1, 2, 1 ], {a:1,b:12} ]) 
//=> [ { a: 1, b: 12 }, [ 2, 1, 2, 1 ], [ 1, 2, 1, 2 ] ]

Ответ 11

Вы можете сделать это в сокращенном виде, например:

_.uniq(foo, 'a')