2015-12-30 12 views
9

Ho un array di pesante come questo:Gruppo per array e aggiungere il campo e la matrice sub in serie principale

[ 
    {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'} 
] 

Cosa devo fare è quello di raggrupparli per optionName e hanno due righe nella matrice principale come this:

[ 
    { 
    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'}] 
    } 
] 

Come si fa in javascript?

risposta

11

Questo è uno snippet che ho scritto per questo tipo di situazioni. Puoi aggiungere questa funzionalità a tutti i tuoi array:

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]}; 
    }); 
    } 
}); 

È possibile utilizzarlo in questo modo. Puoi semplicemente passare una funzione che definisce come vuoi raggruppare i tuoi dati.

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

Working Fiddle

Se avete bisogno, è possibile sostituire con {key: k, data: map[k]}{Name: k, Data: map[k]}.


Questo è anche più compatta versione ES6 del codice di cui sopra:

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

usare in questo modo:

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

È possibile utilizzare ridurre due volte per ottenere il gruppo di risultati è necessario:

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 
}]; 

lista variabile è la vostra prima lista.

Spero che questo aiuti.

0
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 }); 
}); 
0
'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); 

Si può provare questo metodo.

0

Tutte le risposte portano allo stesso risultato, quindi tutto si riduce a una preferenza personale (o linee guida aziendali) su come affrontarlo.

// 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 
     }); 
} 

Questa funzione ti consentirebbe di programmare il risultato desiderato come segue:

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 

Mentre il codice stesso è diversa, è molto simile alle altre risposte, solo con una variazione sui gradini necessario.

Si potrebbe anche scegliere di escludere qualsiasi nome di opzione codificata (Color e Size) estraendo quelli aswel, ciò consentirebbe un input più dinamico, ma potrebbe anche introdurre più elaborazione effettivamente necessaria.

// 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); 
} 

che permette il risultato da pienamente sulla base dei dati di input:

// 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) 
     }); 

Scrivendo tutti i passaggi di dati-pressare in brevi passaggi consice faresti te stesso (in particolare il tuo futuro sé) un favore se questo codice ha bisogno di essere aggiustato.

Se il set di dati è veramente pesante (in termini di di dati), è inoltre necessario assicurarsi di mantenere limitato il numero di copie memorizzate. Ad esempio, se non hai mai bisogno del set di dati originale, assicurati che possa essere raccolto automaticamente (non avendo una variabile che lo contenga al di fuori dell'ambito in cui ricevi i dati)

+0

buona sintesi Rogier, solo una correzione difficile: lei ha citato le soluzioni disponibile in ES6 +, ma array prototype fil ter, map e reduce è disponibile da ES5.1 (2011) e supportato da IE9 +, FF3 + e tutte le versioni di Chrome. –

+0

@AhmetCetin Non sono del tutto sicuro se capisco cosa intendi, nel mio esempio fornisco la sintassi ES5 (.1) aswel come la stessa funzione scritta in ES6 +. Forse ho bisogno di chiarire le prime funzioni per essere ES5 (.1)? –

+0

hai ragione, mi sono perso, hai usato la notazione di freccia grossa in ES6. Sarebbe meglio per la comprensione credo che se si menziona l'altra sintassi è valida per ES5.1. Quando ho letto la prima volta, pensavo che intendessi tutte le soluzioni valide per ES6. –

1

Questo è uno snippet che ho scritto per la mia situazione nella mia funzionalità dell'applicazione di tutti gli array. Questo codice snippet viene utilizzato nell'applicazione nodo js. Tutto quanto sopra è la soluzione data ma stavo trovando qualche problema nel lato server nel nodo js. Questo frammento è utente completa me ....

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; 
} 

Io lo uso come questo. Ho appena passato una funzione che definisce come si desidera raggruppare i nostri dati.

filterData= groupBy(Data,'optionName'); 

Risultato di questo frammento di codice di uscita .....

[ 
{"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"}]} 
] 

Show on fiddle

0

Usage:

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

Risultato:

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

Funzione:

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]) 
} 
3

Una soluzione ES6 utilizzando Map oggetto:

function groupBy(arr, key) { 
 
    \t return arr.reduce(
 
     (sum, item) => { 
 
     \t const groupByVal = item[key]; 
 
     groupedItems = sum.get(groupByVal) || []; 
 
     groupedItems.push(item); 
 
     \t 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>

Problemi correlati