Grouper par tableau et ajouter un champ et un sous-tableau dans le tableau principal

J'ai un tableau lourd comme ceci:

[ {Id: 1, Name: 'Red', optionName: 'Color'}, {Id: 2, Name: 'Yellow', optionName: 'Color'}, {Id: 3, Name: 'Blue', optionName: 'Color'}, {Id: 4, Name: 'Green', optionName: 'Color'}, {Id: 7, Name: 'Black', optionName: 'Color'}, {Id: 8, Name: 'S', optionName: 'Size'}, {Id: 11, Name: 'M', optionName: 'Size'}, {Id: 12, Name: 'L', optionName: 'Size'}, {Id: 13, Name: 'XL', optionName: 'Size'}, {Id: 14, Name: 'XXL', optionName: 'Size'} ] 

Ce que je dois faire est de les regrouper par optionName et avoir deux rangées dans le tableau principal comme ceci:

 [ { Name: 'Color', Data:[{Id: 1, Name: 'Red'}, {Id: 2, Name: 'Yellow'}, {Id: 3, Name: 'Blue'}, {Id: 4, Name: 'Green'}, {Id: 7, Name: 'Black'}] }, { Name: 'Size', Data:[{Id: 8, Name: 'S'}, {Id: 11, Name: 'M'}, {Id: 12, Name: 'L'}, {Id: 13, Name: 'XL'}, {Id: 14, Name: 'XXL'}] } ] 

Comment le faire en javascript?

C'est un extrait que j'ai écrit pour ce genre de situations. Vous pouvez ajouter cette fonctionnalité à tous vos tableaux:

 Object.defineProperty(Array.prototype, 'group', { enumerable: false, value: function (key) { var map = {}; this.forEach(function (e) { var k = key(e); map[k] = map[k] || []; map[k].push(e); }); return Object.keys(map).map(function (k) { return {key: k, data: map[k]}; }); } }); 

Vous pouvez l'utiliser comme ceci. Vous pouvez simplement passer une fonction qui définit comment vous souhaitez grouper vos données.

 var newArray = arr.group(function (item) { return item.optionName; }); 

Fiddle de travail

Si vous avez besoin, vous pouvez remplacer {key: k, data: map[k]} avec {Name: k, Data: map[k]} .


C'est aussi une version ES6 plus compacte du code ci-dessus:

 Object.defineProperty(Array.prototype, 'group', { enumerable: false, value: function (key) { let map = {}; this.map(e => ({k: key(e), d: e})).forEach(e => { map[ek] = map[ek] || []; map[ek].push(ed); }); return Object.keys(map).map(k => ({key: k, data: map[k]})); } }); 

Utilisez-le comme ceci:

 let newArray = arr.group(item => item.optionName)) 

Vous pouvez utiliser deux fois la réduction pour obtenir le jeu de résultats dont vous avez besoin:

 var color = list.reduce(function(memo, item) { if (item.optionName === 'Color') { memo.push({ Id: item.Id, Name: item.Name }); } return memo; }, []); var size = list.reduce(function(memo, item) { if (item.optionName === 'Size') { memo.push({ Id: item.Id, Name: item.Name }); } return memo; }, []); var result = [{ Name: 'Color', Data: color }, { Name: 'Size', Data: size }]; 

La liste des variables est votre première liste.

J'espère que cela t'aides.

Il s'agit d'un extrait que j'ai écrit pour une sorte de situation dans ma fonctionnalité d'application de tous les tableaux. Ce code d'extrait est utilisé dans l'application node js. Tout ce qui précède est donné une solution, mais je trouvais un problème dans le côté du serveur dans les nœuds js. Cet extrait est plein d'utilisateur …

  var Data= [ { Id: 1, Name: 'Red', optionName: 'Color' }, { Id: 2, Name: 'Yellow', optionName: 'Color' }, { Id: 3, Name: 'Blue', optionName: 'Color' }, { Id: 4, Name: 'Green', optionName: 'Color' }, { Id: 7, Name: 'Black', optionName: 'Color' }, { Id: 8, Name: 'S', optionName: 'Size' }, { Id: 11, Name: 'M', optionName: 'Size' }, { Id: 12, Name: 'L', optionName: 'Size' }, { Id: 13, Name: 'XL', optionName: 'Size' }, { Id: 14, Name: 'XXL', optionName: 'Size' } ]; function groupBy(arr, key) { var newArr = [], types = {}, newItem, i, j, cur; for (i = 0, j = arr.length; i < j; i++) { cur = arr[i]; if (!(cur[key] in types)) { types[cur[key]] = { type: cur[key], data: [] }; newArr.push(types[cur[key]]); } types[cur[key]].data.push(cur); } return newArr; } 

Je l'utilise comme ça. Je passe une fonction qui définit comment vous souhaitez grouper nos données.

 filterData= groupBy(Data,'optionName'); 

Résultat de cet extrait de code …

  [ {"type":"Color","data":[{"Id":1,"Name":"Red","optionName":"Color"}, {"Id":2,"Name":"Yellow","optionName":"Color"}, {"Id":3,"Name":"Blue","optionName":"Color"}, {"Id":4,"Name":"Green","optionName":"Color"}, {"Id":7,"Name":"Black","optionName":"Color"}]}, {"type":"Size","data":[{"Id":8,"Name":"S","optionName":"Size"}, {"Id":11,"Name":"M","optionName":"Size"}, {"Id":12,"Name":"L","optionName":"Size"}, {"Id":13,"Name":"XL","optionName":"Size"}, {"Id":14,"Name":"XXL","optionName":"Size"}]} ] 

Montre sur violon

Une solution ES6 utilisant un objet Map:

 function groupBy(arr, key) { return arr.reduce( (sum, item) => { const groupByVal = item[key]; groupedItems = sum.get(groupByVal) || []; groupedItems.push(item); return sum.set(groupByVal, groupedItems); }, new Map() ); } var Data = [ { Id: 1, Name: 'Red', optionName: 'Color' }, { Id: 2, Name: 'Yellow', optionName: 'Color' }, { Id: 3, Name: 'Blue', optionName: 'Color' }, { Id: 4, Name: 'Green', optionName: 'Color' }, { Id: 7, Name: 'Black', optionName: 'Color' }, { Id: 8, Name: 'S', optionName: 'Size' }, { Id: 11, Name: 'M', optionName: 'Size' }, { Id: 12, Name: 'L', optionName: 'Size' }, { Id: 13, Name: 'XL', optionName: 'Size' }, { Id: 14, Name: 'XXL', optionName: 'Size' } ]; document.getElementById("showArray").innerHTML =JSON.stringify([...groupBy(Data, 'optionName')], null, 4); 
 <pre id="showArray"></pre> 
 var originalList = [ { Id: 1, Name: 'Red', optionName: 'Color' }, { Id: 2, Name: 'Yellow', optionName: 'Color' }, { Id: 3, Name: 'Blue', optionName: 'Color' }, { Id: 4, Name: 'Green', optionName: 'Color' }, { Id: 7, Name: 'Black', optionName: 'Color' }, { Id: 8, Name: 'S', optionName: 'Size' }, { Id: 11, Name: 'M', optionName: 'Size' }, { Id: 12, Name: 'L', optionName: 'Size' }, { Id: 13, Name: 'XL', optionName: 'Size' }, { Id: 14, Name: 'XXL', optionName: 'Size' } ]; var output = [{ Name: "Color", Data: [] },{ Name: "Size", Data: [] }] ; originalList.map(function(entry){ if ( entry.optionName === "Color") output[0].Data.push({ Id: entry.Id, Name: entry.Name }); if ( entry.optionName === "Size") output[1].Data.push({ Id: entry.Id, Name: entry.Name }); }); 
 'use strict' let l = [ { Id: 1, Name: 'Red', optionName: 'Color' }, { Id: 2, Name: 'Yellow', optionName: 'Color' }, { Id: 3, Name: 'Blue', optionName: 'Color' }, { Id: 4, Name: 'Green', optionName: 'Color' }, { Id: 7, Name: 'Black', optionName: 'Color' }, { Id: 8, Name: 'S', optionName: 'Size' }, { Id: 11, Name: 'M', optionName: 'Size' }, { Id: 12, Name: 'L', optionName: 'Size' }, { Id: 13, Name: 'XL', optionName: 'Size' }, { Id: 14, Name: 'XXL', optionName: 'Size' } ]; let color = []; let size = []; l.forEach(element => { if (element['optionName'] === 'Color') { color.push({'Id': element.Id, 'Name': element.Name}); } else { size.push({'Id': element.Id, 'Name': element.Name}); } }); console.log(color); console.log(size); 

Vous pouvez essayer cette méthode.

Toutes les réponses mènent au même résultat, donc tout dépend d'une préférence personnelle (ou des lignes directrices de l'entreprise) sur la façon de s'attaquer à cela.

 // ES5 (traditional javascript) version function groupByOptionName(list, optionName) { return list // filter out any item whose optionName does not match the desired name .filter(function(item) { return item.optionName === optionName; }) // map the item into the desired shape // (appears to be everything except optionName itself .map(function(item) { return { Id: item.Id, Name: item.Name }; }) } // ES2015/ES6 version function groupByOptionName(list, optionName) { return list // filter out any item whose optionName does not match the desired name .filter(item => item.optionName === optionName) // map the item into the desired shape // (appears to be everything except optionName itself .map(item => { Id: item.Id, Name: item.Name }); } 

Cette fonction vous permet de programmer le résultat souhaité comme suit:

 var output = [ {Name: 'Color', Data: groupByOptionName(list, 'Color')}, {Name: 'Size', Data: groupByOptionName(list, 'Size')}, ]; // the ES2015/ES6 version of this code would replace var with let 

Alors que le code lui-même diffère, il ressemble beaucoup aux autres réponses, avec seulement une variation des étapes nécessaires.

On pourrait également choisir d'exclure les noms d'options codés ( Color and Size ) en extrayant ces aswel, cela permettrait une entrée plus dynamique, mais pourrait aussi introduire un traitement plus efficace.

 // ES5 (traditional javascript) version function getOptionNames(list) { return list // map the array into a list of optionNames .map(function(item) { return item.optionName; }) // remove duplicates .filter(function(item, index, all) { return all.indexOf(item) === index; }); } // ES2015/ES6 version (does exactly the same as the one above) function getOptionNames(list) { return list // map the array into a list of optionNames .map(item => item.optionName) // remove duplicates .filter((item, index, all) => all.indexOf(item) === index); } 

Ce qui permet au résultat d'être entièrement basé sur les données d'entrée:

 // ES5 (traditional javascript) version var output = getOptionNames(list) // map the names into the desired structure .map(function(buffer, name) { return { Name: name, Data: groupByOptionName(list, name) }; }); // ES2015/ES6 version (does exactly the same as the one above) var output = getOptionNames(list) // map the names into the desired structure .map((buffer, name) => { Name: name, Data: groupByOptionName(list, name) }); 

En écrivant toutes les étapes de gestion des données dans les étapes de consice courte, vous devriez faire vous-même (en particulier votre futur avenir) une faveur si ce code doit être ajusté.

Si l'ensemble de données est vraiment lourd (en termes de beaucoup de données), vous devez également vous assurer de conserver le nombre de copies que vous conservez en mémoire. Par exemple, si vous n'avez jamais besoin de l'ensemble de données original, assurez-vous qu'il peut être récupéré (en n'ayant pas de variable qui le contient en dehors du périmètre où vous recevez les données)

Usage:

 groupValues([ { color: 'blue', value: 100 }, { color: 'blue', value: 75 }, { color: 'yellow', value: 50 }, { color: 'yellow', value: 25 } ], 'color') 

Résultat:

 [ [{ color: 'blue', value: 100 }, { color: 'blue', value: 75 }], [{ color: 'yellow', value: 50 }, { color: 'yellow', value: 25 }] ] 

Fonction:

 const groupValues = function(arr, key) { const mapped = {} arr.forEach(el => { const actualKey = el[key] if(!mapped.hasOwnProperty(actualKey)) mapped[actualKey] = [] mapped[actualKey].push(el) }) return Object.keys(mapped).map(el => mapped[el]) }