web-dev-qa-db-fra.com

Si un élément existe déjà dans un tableau, ne l'ajoutez pas à nouveau

J'ai un tableau d'objets qui ressemble à ceci:

var array = [
    {id:123, value:"value1", name:"Name1"},
    {id:124, value:"value2", name:"Name1"},
    {id:125, value:"value3", name:"Name2"},
    {id:126, value:"value4", name:"Name2"}
    ...
];

Comme vous pouvez le constater, certains noms sont répétés. Je veux obtenir un nouveau tableau avec des noms uniquement, mais si certains noms se répètent, je ne veux pas l'ajouter à nouveau. Je veux ce tableau:

var newArray = ["Name1", "Name2"];

J'essaie de faire cela avec map:

var newArray = array.map((a) => {
    return a.name;
});

Mais le problème est que cela retourne:

newArray = ["Name1", "Name1", "Name2", "Name2"];

Comment puis-je définir une condition dans map, afin qu'elle ne retourne pas un élément qui existe déjà? Je souhaite effectuer cette opération avec map ou une autre fonction ECMAScript 5 ou ECMAScript 6.

85
snoopy25

Avec ES6, vous pouvez utiliser Set pour des valeurs uniques, après avoir mappé uniquement les noms des objets.

Cette proposition utilise une syntaxe spread ... pour collecter les éléments dans un nouveau tableau.

const array = [{ id: 123, value: "value1", name:"Name1" }, { id: 124, value: "value2", name: "Name1" }, { id: 125, value: "value3", name: "Name2" }, { id: 126, value: "value4", name: "Name2" }],
      names = [...new Set(array.map(a => a.name))];

console.log(names);

174
Nina Scholz

Si vous recherchez une solution JavaScript autre que ES 6 (pas de set), vous pouvez utiliser la méthode reduce de Array :

var array=[
  {id:123, value:"value1", name:"Name1"},
  {id:124, value:"value2", name:"Name1"},
  {id:125, value:"value3", name:"Name2"},
  {id:126, value:"value4", name:"Name2"}
];
var names = array.reduce(function (a, b) {
  if (a.indexOf(b.name) == -1) {
    a.Push(b.name)
  }
  return a;
}, []);

console.log(names);

56
Dekel

Personnellement, je ne vois pas pourquoi tout le monde s'emballe avec ES 6. Si c'était mon code, je préférerais supporter autant de navigateurs que possible.

var array=[
{id:123, value:"value1", name:"Name1"},
{id:124, value:"value2", name:"Name1"},
{id:125, value:"value3", name:"Name2"},
{id:126, value:"value4", name:"Name2"}
];

   // Create array of unique names
var a = (function(a){
  for (var i = array.length; i--;)
    if (a.indexOf(array[i].name) < 0) a.Push(array[i].name);
  return a;
})([]);

console.log(a);

15
iwrestledabearonce

Vous pouvez également simplement combiner map avec filter

var array = [
  {id:123, value:"value1", name:"Name1"},
  {id:124, value:"value2", name:"Name1"},
  {id:125, value:"value3", name:"Name2"},
  {id:126, value:"value4", name:"Name2"}
];

var unique = array
  .map( item => item.name )
  .filter( ( item, idx, arr ) => arr.indexOf( item ) == idx ) 

console.log(unique)

11
DavidDomain

Vous pouvez faire Array.prototype.map () pour obtenir un tableau avec les propriétés name et/ Array.prototype.filter () en utilisant les paramètres elem, index et array, dans le prédicat de fonction pour éliminer les éléments répétés:

var array = [{id:123, value:"value1", name:"Name1"}, {id:124, value:"value2", name:"Name1"}, {id:125, value:"value3", name:"Name2"}, {id:126, value:"value4", name:"Name2"}],
    names = array
      .map(e => e.name)
      .filter((e, i, a) => a.indexOf(e) === i);

console.log(names);

9
Yosvel Quintero

Je conviens que si vous avez uniquement besoin des valeurs name, une Set est la voie à suivre. 

Cependant, si vous souhaitez obtenir un tableau d'objets uniques basé sur la propriété name, il est conseillé d'utiliser un Map . Un moyen rapide de créer une carte consiste à utiliser un tableau de tableaux [key, value]:

const array = [{ id: 123, value: "value1", name:"Name1" }, { id: 124, value: "value2", name: "Name1" }, { id: 125, value: "value3", name: "Name2" }, { id: 126, value: "value4", name: "Name2" }],
      unique = new Map(array.map(obj => [obj.name, obj]));

// To get the unique objects
const uniques = Array.from(unique.values());

// Get the names like you already did:
console.log("Names:", uniques.map(obj => obj.name));

// If you ever need the complete array of unique objects, you got a ref:
console.log(JSON.stringify(uniques));
.as-console-wrapper { min-height: 100%; }

Un avantage supplémentaire de Map est que vous obtenez à la fois la fonctionnalité filter qui supprime les non-uniques, sans perdre la connexion avec les objets source. Bien sûr, cela n'est nécessaire que si vous devez référencer plusieurs fois le jeu d'objets unique.

6
user3297291

Beaucoup de bonnes réponses ici. Je voudrais juste contribuer avec une certaine diversité en espérant vous donner une autre perspective.

Les tableaux sont de type objet en JavaScript, ils peuvent donc être utilisés simultanément comme hachage. En utilisant cette fonctionnalité, nous pouvons grandement simplifier le travail à effectuer en une seule opération de réduction avec une complexité de temps O(n).

Si votre tableau ne contient pas certaines propriétés autres que les clés de tableau, vous pouvez également envisager de conserver un objet de hachage distinct.

var array = [{id:123, value:"value1", name:"Name1"},
             {id:124, value:"value2", name:"Name1"},
             {id:125, value:"value3", name:"Name2"},
             {id:126, value:"value4", name:"Name2"}
            ],
result = array.reduce((p,c) => p[c.name] ? p : (p[c.name] = true, p.Push(c.name), p), []);
console.log(result);

6
Redu

Si vous êtes limité à ES5, je voudrais utiliser Le _.uniq de Lodash

var newArray = _.uniq(array.map(function(a) {
  return a.name;
}));
3
AndrewHenderson

Avec ES6, cela devrait faire l'affaire.

var array=[
    {id:123, value:"value1", name:"Name1"},
    {id:124, value:"value2", name:"Name1"},
    {id:125, value:"value3", name:"Name2"},
    {id:126, value:"value4", name:"Name2"}
];

var set = new Set();

array.forEach((a)=>{
    set.add(a.name);
}); 

console.log(Array.from(set));

2
kkreft

Dans ES5, utilisez un objet comme dictionnaire pour les performances O ( n ).

Cela ne fonctionnera que si toutes les clés sont des chaînes.

var array = [
    {id: 123, value: "value1", name: "Name1"},
    {id: 124, value: "value2", name: "Name1"},
    {id: 125, value: "value3", name: "Name2"},
    {id: 126, value: "value4", name: "Name2"}
];

var allNames = array.map(item => item.name);

var map = {};
allNames.forEach(name => {
  map[name] = true;
});
var uniqueNames = Object.keys(map);

console.log(uniqueNames);

Vous pouvez faire la même chose en une seule expression si vous aimez:

var uniqueNames = Object.keys(allNames.reduce((m, n) => (m[n] = true, m), {}));

mais je trouve la forme impérative plus facile à lire.

0
joeytwiddle

En utilisant UnderscoreJS,

array = [{id:123, value:"value1", name:"Name1"}, {id:124, value:"value2", name:"Name1"}, {id:125, value:"value3", name:"Name2"}, {id:126, value:"value4", name:"Name2"}];
get_names =  _.pluck(_.uniq(array, 'name'), 'name')
console.log(get_names)
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>

0

Essaye ça:

nArr = [];
array.forEach((a) => {
    if (nArr.indexOf(a.name) < 0) { 
        nArr.Push(a.name); 
    }
}); 
0

C'est comme ça que je l'ai fait, en utilisant un tableau vide séparé.

var array = [
   {id:123, value:"value1", name:"Name1"},
   {id:124, value:"value2", name:"Name1"},
   {id:125, value:"value3", name:"Name2"},
   {id:126, value:"value4", name:"Name2"}	    
];

var array2 = []		
		
for (i=0; i<array.length;i++){						
   if (array2.indexOf(array[i].name) == -1){				
     array2.Push(array[i].name);
    }
}			

console.log(array2)	

0
Abhishek Gurjar