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 pricearrayWithDuplicates, 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é.

22
demandé sur Lauren F 2015-08-27 03:01:49

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; });
4
répondu user3335966 2015-08-27 05:00:21
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.

21
répondu Tamas Hegedus 2015-08-27 09:14:45

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"
    }
]
8
répondu yvesmancera 2015-08-27 00:20:41

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;
    });
}
6
répondu gilly3 2015-08-27 00:29:45

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

1
répondu yureka 2017-01-09 12:37:17

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);
    }
});
1
répondu Souvik Basu 2017-08-14 07:11:57

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!

0
répondu jh3y 2015-08-27 00:43:48

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');
0
répondu Praveen M P 2017-12-01 11:41:42
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);
0
répondu sudha priya 2018-07-02 06:26:00

Vous pouvez utiliser lodash pour supprimer dupliquer des objets:

 import * as _ from 'lodash';
  _.uniqBy(data, 'id');

Iciid' est votre identifiant unique

0
répondu Mukesh Ranjan 2018-07-10 05:04:39