J'ai ce genre de tableau:
var foo = [ { "a" : "1" }, { "b" : "2" }, { "a" : "1" } ];
Je voudrais le filtrer pour avoir:
var bar = [ { "a" : "1" }, { "b" : "2" }];
J'ai essayé d'utiliser _.uniq, mais je suppose que, parce que { "a" : "1" }
n'est pas égal à lui-même, cela ne fonctionne pas. Existe-t-il un moyen de fournir à uniq de soulignement une fonction d’égalité surchargée?
.uniq/ .unique accepte un rappel
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}]
Remarques:
Autre exemple: utiliser le rappel pour extraire les marques de voiture, les couleurs d’une liste
Si vous souhaitez supprimer les doublons en fonction d'un identifiant, vous pouvez procéder comme suit:
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'}]
Mise en œuvre de la réponse de 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" } ]
Quand j'ai un identifiant d'attribut, c'est ma manière préférée de souligner:
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}]
Utiliser underscore unique lib est le suivant, je m’offre une liste unique sur la base de _id, puis je renvoie la valeur String de _id:
var uniqueEntities = _.uniq(entities, function (item, key, a) {
return item._id.toString();
});
Voici une solution simple, qui utilise une comparaison d'objet approfondie pour vérifier les doublons (sans recourir à la conversion en JSON, ce qui est inefficace et fastidieux)
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;
});
Il filtre tous les éléments s'ils ont un duplicata plus tard dans le tableau - de sorte que le dernier élément dupliqué soit conservé.
Le test de duplication utilise _.isEqual
qui effectue une comparaison approfondie optimisée entre les deux objets. Pour plus d’informations, consultez le underscore isEqual documentation .
edit: mis à jour pour utiliser _.filter
qui est une approche plus propre
Essayez la fonction itérateur
Par exemple, vous pouvez retourner le premier élément
x = [['a',1],['b',2],['a',1]]
_.uniq(x,false,function(i){
return i[0] //'a','b'
})
=> [['' a ', 1], [' b ', 2]]
avec underscore, j'ai dû utiliser String () dans la fonction iteratee
function isUniq(item) {
return String(item.user);
}
var myUniqArray = _.uniq(myArray, isUniq);
voici ma solution (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
exemple:
_.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 ] ]
var foo = [ { "a" : "1" }, { "b" : "2" }, { "a" : "1" } ];
var bar = _.map(_.groupBy(foo, function (f) {
return JSON.stringify(f);
}), function (gr) {
return gr[0];
}
);
Permet de décomposer cela. Commençons par regrouper les éléments du tableau en fonction de leur valeur stringifiée
var grouped = _.groupBy(foo, function (f) {
return JSON.stringify(f);
});
grouped
ressemble à:
{
'{ "a" : "1" }' = [ { "a" : "1" } { "a" : "1" } ],
'{ "b" : "2" }' = [ { "b" : "2" } ]
}
Prenons ensuite le premier élément de chaque groupe
var bar = _.map(grouped, function(gr)
return gr[0];
});
bar
ressemble à: [ { "a" : "1" }, { "b" : "2" } ]
Mets le tout ensemble:
var foo = [ { "a" : "1" }, { "b" : "2" }, { "a" : "1" } ];
var bar = _.map(_.groupBy(foo, function (f) {
return JSON.stringify(f);
}), function (gr) {
return gr[0];
}
);
Je voulais résoudre cette solution simple de manière simple, avec un peu de frais de calcul ... mais n'est-ce pas une solution triviale avec une définition de variable minimale, n'est-ce pas?
function uniq(ArrayObjects){
var out = []
ArrayObjects.map(obj => {
if(_.every(out, outobj => !_.isEqual(obj, outobj))) out.Push(obj)
})
return out
}