Combinaison de tableaux d’objects ({a: a, b: b, c: c}, {a: a, d: d, c: c}) à ({a: a, b: c, d: c})

J’ai une liste de données que je reçois que je dois convertir et “pivoter” pour transformer une colonne en plusieurs colonnes.

La liste des objects que j’ai ressemble à ceci:

var list = [ { "date": "2016-05-31", "action": "test", "value": 10 }, { "date": "2016-05-31", "action": "run", "value": 8 }, { "date": "2016-06-01", "action": "delete", "value" : 2 }, { "date": "2016-06-01", "action": "test", "value": 5 }, ] 

J’ai besoin de convertir ceci pour une bibliothèque de graphiques afin qu’il ressemble à ceci:

 var list = [ { "date": "2016-05-31", "test": 10, "run": 8, "delete": 0 }, { "date": "2016-06-01", "test": 5, "run": 0, "delete": 2 } ] 

Existe-t-il un moyen assez facile de faire cela en utilisant des fonctions underscore.js telles que _.groupBy et _.map etc …?

Voici une solution ES6, qui ne teste pas, n’exécute pas, ne delete pas en dur, mais récupère d’abord toutes les actions possibles dans les données:

 function pivot(list) { var actions = list.reduce( (actions, o) => (actions[o.action] = 0, actions), {} ); var res = list.reduce( (res, o) => ((res[o.date] = res[o.date] || Object.assign({ date: o.date }, actions))[o.action] += o.value, res), {}); return Object.keys(res).map(key => res[key]); } // Sample data var list = [{ "date": "2016-05-31", "action": "test", "value": 10 }, { "date": "2016-05-31", "action": "run", "value": 8 }, { "date": "2016-06-01", "action": "delete", "value": 2 }, { "date": "2016-06-01", "action": "test", "value": 5 }]; // Call var res = pivot(list); // Output console.log(res); 

Cela itère deux fois pour créer une carte des dates, puis à nouveau pour insérer les propriétés manquantes?

 var list = [{ "date": "2016-05-31", "action": "test", "value": 10 }, { "date": "2016-05-31", "action": "run", "value": 8 }, { "date": "2016-06-01", "action": "delete", "value": 2 }, { "date": "2016-06-01", "action": "test", "value": 5 }]; var map = {}; list.forEach(function(o) { if ( !(o.date in map) ) map[o.date] = {}; map[o.date][o.action] = o.value; }); var sorted_list = Object.keys(map).map(function(k) { return { "date" : k, "test" : (map[k].test || 0), "run" : (map[k].run || 0), "delete" : (map[k].delete || 0) } }); document.body.innerHTML = '
' + JSON.ssortingngify(sorted_list, 0, 4) + '

';

Voici une façon de le faire, en utilisant .reduce() pour créer un object temporaire pour accumuler les valeurs, puis .map() pour créer le tableau final:

 var temp = list.reduce(function(c, v) { (c[v.date] || (c[v.date]={}))[v.action] = v.value; return c; }, {}); var output = Object.keys(temp).map(function(k) { return { date : k, test : temp[k].test || 0, run : temp[k].run || 0, "delete" : temp[k].delete || 0 } }); 

Voici une solution Underscore:

 var result = _.chain(list).groupBy("date") .mapObject(function(item, key) { var d = {date: key}; for(var i in item) d[item[i].action] = item[i].value; return d; }).values().value(); 
 var list = [{ "date": "2016-05-31", "action": "test", "value": 10 }, { "date": "2016-05-31", "action": "run", "value": 8 }, { "date": "2016-06-01", "action": "delete", "value": 2 }, { "date": "2016-06-01", "action": "test", "value": 5 }, ]; var result = _.chain(list).groupBy("date") .mapObject(function(item, key) { var d = {date: key}; for(var i in item) d[item[i].action] = item[i].value; return d; }).values().value(); console.log(result);