web-dev-qa-db-fra.com

Exécuter .join sur une valeur dans un tableau d'objets

Si j'ai un tableau de chaînes, je peux utiliser la méthode .join() pour obtenir une seule chaîne, chaque élément étant séparé par une virgule, comme suit:

["Joe", "Kevin", "Peter"].join(", ") // => "Joe, Kevin, Peter"

J'ai un tableau d'objets et j'aimerais effectuer une opération similaire sur une valeur détenue à l'intérieur de celui-ci; donc de

[
  {name: "Joe", age: 22},
  {name: "Kevin", age: 24},
  {name: "Peter", age: 21}
]

exécutez la méthode join uniquement sur l'attribut name pour obtenir le même résultat qu'auparavant.

Actuellement, j'ai la fonction suivante:

function joinObj(a, attr){
  var out = [];

  for (var i = 0; i < a.length; i++){
    out.Push(a[i][attr]);
  }

  return out.join(", ");
}

Il n’ya rien de mal avec ce code, il fonctionne, mais tout à coup, je suis passé d’une simple ligne de code succinct à une fonction très impérative. Existe-t-il une manière plus succincte, idéalement plus fonctionnelle, d’écrire ceci?

228
jackweirdy

Vous pouvez toujours remplacer la méthode toString de vos objets:

var arr = [
    {name: "Joe", age: 22, toString: function(){return this.name;}},
    {name: "Kevin", age: 24, toString: function(){return this.name;}},
    {name: "Peter", age: 21, toString: function(){return this.name;}}
];

var result = arr.join(", ");
//result = "Joe, Kevin, Peter"
67
basilikum

J'ai aussi rencontré la méthode reduce, voici à quoi ça ressemble:

[
  {name: "Joe", age: 22},
  {name: "Kevin", age: 24},
  {name: "Peter", age: 21}
].reduce(function (a, b) {return (a.name || a) + ", " + b.name})

Le (a.name || a) est tel que le premier élément est traité correctement, mais le reste (où a est une chaîne et donc a.name n'est pas défini) n'est pas traité comme un objet.

Edit: je l'ai maintenant refactored suite à ceci:

x.reduce(function(a, b) {return a + ["", ", "][+!!a.length] + b.name;}, "");

ce qui, je crois, est plus propre, car a est toujours une chaîne, b est toujours un objet (en raison de l'utilisation du paramètre optionnel initialValue dans reduce)

Edit 6 mois plus tard: Oh, à quoi je pensais. "nettoyeur". J'ai mis en colère les Dieux du code.

9
jackweirdy

Je ne sais pas s'il existe un moyen plus simple de le faire sans utiliser une bibliothèque externe, mais personnellement, j'aime l'amour nderscore.js = qui a des tonnes d’utilitaires pour traiter les tableaux, les collections, etc.

Avec soulignement, vous pouvez le faire facilement avec une seule ligne de code:

_.pluck(arr, 'name').join(', ')

8
Ed Hinchliffe

Sur noeud ou ES6:

users.map(u => u.name).join(', ')

3
ariel

disons que le tableau d'objets est référencé par la variable users

Si ES6 peut être utilisé, la solution la plus simple sera:

users.map(user => user.name).join(', ');

Sinon, et lodash peut être utilisé pour:

 _.map(users, function(user) {
     return user.name;
 }).join(', ');
2
C'estLaVie

Si objet et clés dynamiques: "applications\":{\"1\":\"Element1\",\"2\":\"Element2\"}

Object.keys(myObject).map(function (key, index) {
    return myObject[key]
}).join(', ')
1
Davron Achilov

Un vieux fil que je connais mais qui reste très pertinent pour quiconque rencontre cela.

Array.map a été suggéré ici, qui est une méthode géniale que j'utilise tout le temps. Array.reduce a également été mentionné ...

Personnellement, j'utiliserais un Array.reduce pour ce cas d'utilisation. Pourquoi? Malgré le code étant légèrement moins propre/clair. C’est beaucoup plus efficace que d’attribuer la fonction de carte à une jointure.

La raison en est que Array.map doit boucler sur chaque élément pour renvoyer un nouveau tableau avec tous les noms de l'objet dans le tableau. Array.join parcourt ensuite le contenu du tableau pour effectuer la jointure.

Vous pouvez améliorer la lisibilité de jackweirdys réduire la réponse en utilisant des littéraux de modèle pour obtenir le code sur une seule ligne. "Supporté dans tous les navigateurs modernes aussi"

// a one line answer to this question using modern JavaScript
x.reduce((a, b) => `${a.name || a}, ${b.name}`);
0
Nigelli

pas sûr, mais tout cela répond qu'ils fonctionnent mais ne sont pas optimaux car ils effectuent deux analyses et vous pouvez effectuer ceci en une seule analyse. Même si O(2n) est considéré comme O(n), il est toujours préférable d'avoir un vrai O (n).

const Join = (arr, separator, prop) => {
    let combined = '';
    for (var i = 0; i < arr.length; i++) {
        combined = `${combined}${arr[i][prop]}`;
        if (i + 1 < arr.length)
            combined = `${combined}${separator} `;
    }
    return combined;
}

Cela peut ressembler à la vieille école, mais me permet de faire comme ça:

skuCombined = Join(option.SKUs, ',', 'SkuNum');
0
Jorge Aguilar