J'ai un tableau d'objets que j'aimerais réduire en fonction d'une paire key:value
spécifique. Je veux créer un tableau qui ne comprend qu'un seul objet par cette paire key:value
spécifique. Peu importe quel objet des doublons est copié dans le nouveau tableau.
Par exemple, je souhaite couper en fonction de la propriété price
de arrayWithDuplicates
, en créant un nouveau tableau qui n'inclut qu'une seule de chaque 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
}
}
];
Deviendrait:
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 un JavaScript ou une fonction angulaire qui ferait une boucle et le ferait?
EDIT: La propriété à filtrer est imbriquée dans une autre propriété.
Vous pouvez utiliser underscore pour cela:
//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 (les fonctions de flèche d'EcmaScript6 améliorent l'apparence):
removeDuplicatesBy(x => x.custom.price, yourArrayWithDuplicates);
EDIT: extrait modifié pour ne pas utiliser le nom de la propriété, mais pour utiliser une fonction de sélecteur de clé, afin que vous puissiez accéder aux propriétés imbriquées.
Je ne pense pas qu'il existe une fonction intégrée dans Angular, mais il n'est pas difficile d'en créer une:
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');
Résultats:
[
{
"color": "red",
"size": "small"
},
{
"color": "blue",
"size": "medium"
},
{
"color": "red",
"size": "large"
}
]
Et
removeDuplicates(arrayWithDuplicates, 'color');
Résultats:
[
{
"color": "red",
"size": "small"
},
{
"color": "green",
"size": "small"
},
{
"color": "blue",
"size": "medium"
}
]
Utilisez Array.filter()
, en gardant une trace des valeurs en utilisant une Object
comme hachage et en filtrant les éléments dont la valeur est déjà contenue dans le hachage.
function trim(arr, key) {
var values = {};
return arr.filter(function(item){
var val = item[key];
var exists = values[val];
values[val] = true;
return !exists;
});
}
Vous pouvez utiliser lodash pour supprimer les objets en double:
import * as _ from 'lodash';
_.uniqBy(data, 'id');
Ici 'id
' est votre identifiant unique
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);
Solution simple mais pas la plus performante:
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);
}
});
en utilisant lodash
, vous pouvez le filtrer facilement
le premier paramètre sera votre tableau et le second sera votre champ avec les doublons
_.uniqBy(arrayWithDuplicates, 'color')
il retournera un tableau avec une valeur unique
Essayez la fonction suivante:
function trim(items){
const ids = [];
return items.filter(item => ids.includes(item.id) ? false : ids.Push(item.id));
}
De prime abord, aucune fonction ne le fera pour vous car vous traitez avec un tableau d'objets et il n'y a pas non plus de règle pour laquelle les doublons seraient supprimés comme doublons.
Dans votre exemple, vous supprimez celui avec size: small
, mais si vous deviez l'implémenter à l'aide d'une boucle, vous incluriez probablement le premier et excluiez le dernier lorsque vous parcourez votre tableau.
Il peut être intéressant de regarder une bibliothèque telle que lodash et de créer une fonction qui utilise une combinaison de ses méthodes d’API pour obtenir le comportement souhaité.
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 doublon avant d’être attaché à un résultat renvoyé.
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 des ouvrages sur le filtrage des tableaux ici Si vous devez indiquer une préférence sur l'élément à supprimer, vous pouvez définir des paramètres et une logique supplémentaires permettant d'effectuer des contrôles de propriété supplémentaires avant d'ajouter une valeur de retour.
J'espère que cela pourra aider!
Voici la méthode TypeScript
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');
Ceci est juste une autre 'fonctionnalité' basée sur la solution de yvesmancera (après que j'ai commencé à bricoler pour ma propre solution). Nous avons également noté que nous ne sommes autorisés à utiliser que IE 11, une version limitée de ES5 est donc autorisée.
var newArray = RemoveDuplicates(myArray,'Role', 2);
function RemoveDuplicates(array, objKey, rtnType) {
var list = [], values = [], value;
for (var i = 0; i < array.length; i++) {
value = array[i][objKey];
if(values.indexOf(value) === -1){
list.Push(array[i]);
values.Push(value);
}
}
if(rtnType == 1)
return list;
return values;
};
En espérant que cela fonctionnera pour la plupart des tableaux, sinon pour tous, lors du filtrage des objets en fonction d'une valeur de propriété d'objet unique.