J'ai cet exemple de données renvoyé par une API.
J'utilise le _.groupBy
de Lodash pour convertir les données en un objet que je peux mieux utiliser .
[
{
"name": "jim",
"color": "blue",
"age": "22"
},
{
"name": "Sam",
"color": "blue",
"age": "33"
},
{
"name": "eddie",
"color": "green",
"age": "77"
}
]
Je veux que la fonction _.groupBy
renvoie un objet qui ressemble à ceci:
[
{
color: "blue",
users: [
{
"name": "jim",
"color": "blue",
"age": "22"
},
{
"name": "Sam",
"color": "blue",
"age": "33"
}
]
},
{
color: "green",
users: [
{
"name": "eddie",
"color": "green",
"age": "77"
}
]
}
]
J'utilise actuellement
_.groupBy(a, function(b) { return b.color})
qui retourne ceci.
{blue: [{..}], green: [{...}]}
les regroupements sont corrects, mais j'aimerais vraiment ajouter les clés que je veux (color
, users
). Est-ce possible d'utiliser _.groupBy
? ou un autre utilitaire LoDash
?
Tu peux le faire comme ça
var result = _.chain(data)
.groupBy("color")
.pairs()
.map(function(currentItem) {
return _.object(_.Zip(["color", "users"], currentItem));
})
.value();
console.log(result);
Remarque: à partir de Lodash 4.0, la fonction .pairs
a été renommée _.toPairs()
N'est-ce pas aussi simple?
var result = _(data)
.groupBy(x => x.color)
.map((value, key) => ({color: key, users: value}))
.value();
autrement
_.chain(data)
.groupBy('color')
.map((users, color) => ({ users, color }))
.value();
La réponse la plus votée utilise la fonction Lodash _.chain
qui est maintenant considérée comme une mauvaise pratique"Pourquoi utiliser _.chain
est une erreur."
Voici quelques lignes qui abordent le problème de la perspective programmation fonctionnelle:
import tap from "lodash/fp/tap";
import flow from "lodash/fp/flow";
import groupBy from "lodash/fp/groupBy";
const map = require('lodash/fp/map').convert({ 'cap': false });
const result = flow(
groupBy('color'),
map((users, color) => ({color, users})),
tap(console.log)
)(input)
Où input
est un tableau que vous souhaitez convertir.
Merci @thefourtheye, votre code a grandement aidé. J'ai créé une fonction générique à partir de votre solution à l'aide de la version 4.5.0 de Lodash.
function groupBy(dataToGroupOn, fieldNameToGroupOn, fieldNameForGroupName, fieldNameForChildren) {
var result = _.chain(dataToGroupOn)
.groupBy(fieldNameToGroupOn)
.toPairs()
.map(function (currentItem) {
return _.zipObject([fieldNameForGroupName, fieldNameForChildren], currentItem);
})
.value();
return result;
}
Pour l'utiliser:
var result = groupBy(data, 'color', 'colorId', 'users');
Voici le violoniste mis à jour;
Voici une version mise à jour utilisant lodash 4 et ES6
const result = _.chain(data)
.groupBy("color")
.toPairs()
.map(pair => _.zipObject(['color', 'users'], pair))
.value();
Je suggérerais une approche différente, en utilisant ma propre bibliothèque vous pouvez le faire en quelques lignes:
var groupMe = sequence(
groupBy(pluck('color')),
forOwn(function(acc, k, v) {
acc.Push({colors: k, users: v});
return acc;
},[])
);
var result = groupMe(collection);
Cela serait un peu difficile avec lodash ou Underscore car les arguments sont dans l’ordre inverse, il faudrait donc beaucoup utiliser _.partial
.
Exemple groupBy et somme d'une colonne avec Lodash 4.17.4
var data = [{
"name": "jim",
"color": "blue",
"amount": 22
}, {
"name": "Sam",
"color": "blue",
"amount": 33
}, {
"name": "eddie",
"color": "green",
"amount": 77
}];
var result = _(data)
.groupBy(x => x.color)
.map((value, key) =>
({color: key,
totalamount: _.sumBy(value,'amount'),
users: value})).value();
console.log(result);