JavaScript: supprimer les doublons d'objets ayant la même valeur de propriété
j'ai un tableau d'objets que je voudrais réduire en fonction d'unkey:value
la paire. Je veux créer un tableau qui ne comprend qu'un seul objet par ce key:value
la paire. Il n'importe pas nécessairement quel objet des doublons est copié dans le nouveau tableau.
Par exemple, je veux garniture basé sur le price
arrayWithDuplicates
, créant un nouveau tableau qui n'inclut qu'une seule valeur:
var arrayWithDuplicates = [
{"color":"red",
"size": "small",
"custom": {
"inStock": true,
"price": 10
}
},
{"color":"green",
"size": "small",
"custom": {
"inStock": true,
"price": 30
}
},
{"color":"blue",
"size": "medium",
"custom": {
"inStock": true,
"price": 30
}
},
{"color":"red",
"size": "large",
"custom": {
"inStock": true,
"price": 20
}
}
];
devenir:
var trimmedArray = [
{"color":"red",
"size": "small",
"custom": {
"inStock": true,
"price": 10
}
},
{"color":"green",
"size": "small",
"custom": {
"inStock": true,
"price": 30
}
},
{"color":"red",
"size": "large",
"custom": {
"inStock": true,
"price": 20
}
}
];
Existe-t-il une fonction JavaScript ou angulaire qui ferait une boucle et ferait cela?
EDIT: la propriété à filtrer est imbriquée dans une autre propriété.
10 réponses
Vous pouvez utiliser soulignement pour ceci:
//by size:
var uSize = _.uniq(arrayWithDuplicates, function(p){ return p.size; });
//by custom.price;
var uPrice = _.uniq(arrayWithDuplicates, function(p){ return p.custom.price; });
function removeDuplicatesBy(keyFn, array) {
var mySet = new Set();
return array.filter(function(x) {
var key = keyFn(x), isNew = !mySet.has(key);
if (isNew) mySet.add(key);
return isNew;
});
}
utilisation (EcmaScript6 flèche fonctions rend mieux):
removeDuplicatesBy(x => x.custom.price, yourArrayWithDuplicates);
EDIT: extrait édité pour ne pas utiliser le nom de la propriété, mais pour utiliser une fonction de sélecteur de clé, de sorte que vous pouvez atteindre les propriétés imbriquées.
je ne pense pas qu'il y a une fonction intégrée dans Angulaire, mais il n'est pas difficile de créer un:
function removeDuplicates(originalArray, objKey) {
var trimmedArray = [];
var values = [];
var value;
for(var i = 0; i < originalArray.length; i++) {
value = originalArray[i][objKey];
if(values.indexOf(value) === -1) {
trimmedArray.push(originalArray[i]);
values.push(value);
}
}
return trimmedArray;
}
Utilisation:
removeDuplicates(arrayWithDuplicates, 'size');
Renvoie:
[
{
"color": "red",
"size": "small"
},
{
"color": "blue",
"size": "medium"
},
{
"color": "red",
"size": "large"
}
]
Et
removeDuplicates(arrayWithDuplicates, 'color');
Renvoie:
[
{
"color": "red",
"size": "small"
},
{
"color": "green",
"size": "small"
},
{
"color": "blue",
"size": "medium"
}
]
Utiliser Array.filter()
, garder la trace des valeurs à l'aide d'un Object
comme un hash, et en filtrant tous les éléments dont la valeur est déjà contenue dans le hash.
function trim(arr, key) {
var values = {};
return arr.filter(function(item){
var val = item[key];
var exists = values[val];
values[val] = true;
return !exists;
});
}
en utilisant lodash
vous pouvez filtrer facilement
le premier paramètre sera votre tableau et le second sera votre terrain avec des doublons
_.uniqBy(arrayWithDuplicates, 'color')
il retournera un tableau avec une valeur unique
la solution la plus Simple mais pas le plus performant:
var unique = [];
duplicates.forEach(function(d) {
var found = false;
unique.forEach(function(u) {
if(u.key == d.key) {
found = true;
}
});
if(!found) {
unique.push(d);
}
});
hors de ma tête il n'y a pas une seule fonction qui fera cela pour vous car vous avez affaire à un tableau d'objets et aussi il n'y a pas de règle pour laquelle le dupliqué serait supprimé comme dupliqué.
Dans votre exemple, vous supprimez l'un avec size: small
mais si vous deviez implémenter ceci en utilisant une boucle, vous incluriez très probablement la première et excluriez la dernière au fur et à mesure que vous bouclez votre tableau.
il peut très bien être intéressant de jeter un coup d'oeil à une bibliothèque telle que lodash et créer une fonction qui utilise une combinaison de ses méthodes API pour obtenir le comportement désiré.
Voici une solution possible que vous pourriez utiliser en utilisant des tableaux de base et une expression de filtre pour vérifier si un nouvel élément serait considéré comme un duplicata avant d'être attaché à un résultat de retour.
var arrayWithDuplicates = [
{"color":"red", "size": "small"},
{"color":"green", "size": "small"},
{"color":"blue", "size": "medium"},
{"color":"red", "size": "large"}
];
var reduce = function(arr, prop) {
var result = [],
filterVal,
filters,
filterByVal = function(n) {
if (n[prop] === filterVal) return true;
};
for (var i = 0; i < arr.length; i++) {
filterVal = arr[i][prop];
filters = result.filter(filterByVal);
if (filters.length === 0) result.push(arr[i]);
}
return result;
};
console.info(reduce(arrayWithDuplicates, 'color'));
vous pouvez consulter quelques publications sur le filtrage des tableaux ici Si vous avez besoin de fournir une préférence sur l'élément à supprimer vous pourriez définir des paramètres supplémentaires et de la logique qui feront des vérifications de propriétés supplémentaires avant d'ajouter à une valeur de retour.
espérons que cela aide!
Voici le tapuscrit
public removeDuplicates(originalArray:any[], prop) {
let newArray = [];
let lookupObject = {};
originalArray.forEach((item, index) => {
lookupObject[originalArray[index][prop]] = originalArray[index];
});
Object.keys(lookupObject).forEach(element => {
newArray.push(lookupObject[element]);
});
return newArray;
}
Et
let output = this.removeDuplicates(yourArray,'color');
for (let i = 0; i < arrayWithDuplicates.length; i++) {
for (let j = i + 1; j < arrayWithDuplicates.length; j++) {
if (arrayWithDuplicates[i].name === students[j].name) {
arrayWithDuplicates.splice(i, 1);
}
}
}
this will work perfectly...and this will delete first repeated array.
To delete last repeated array we only have to change
arrayWithDuplicates.splice(i, 1) ; into
arrayWithDuplicates.splice(j, 1);
Vous pouvez utiliser lodash pour supprimer dupliquer des objets:
import * as _ from 'lodash';
_.uniqBy(data, 'id');
Iciid
' est votre identifiant unique