2017-10-18 5 views
1

Ich versuche derzeit, Funktionen zuzuordnen und zu reduzieren, um ein mehrdimensionales Array zu reduzieren.
Dies ist ein Pseudo-Beispiel Datensatz:Multidimensionales Array reduzieren

data: [ 
    { 
    label: "Sort-01" 
    data: [ 
     { 
     label: "OCT-2017" 
     weight: 2304 
     }, 
     { 
     label: "NOV-2017" 
     weight: 1783 
     } 
    ] 
    }, 
    { 
    label: "Sort-02" 
    data: [ 
     { 
     label: "OCT-2017" 
     weight: 4785 
     }, 
     { 
     label: "NOV-2017" 
     weight: 102 
     } 
    ] 
    }, 
...... 
] 

Ich weiß, um durch Sortiernummer zur Karte-reduziere ich verwenden können:

data.map(sort => sort.data.reduce((a,b) => a.weight + b.weight)); 

Allerdings habe ich durch den Monat reduzieren wollen, anstatt Nummer sortieren.
Ich würde jede Hilfe zu schätzen wissen.

Danke,
Jay

Antwort

2

Verwenden Array # Karte die ein Array der data Eigenschaften Array zu erhalten, dann mit Array#concat und spread glätten. Verwenden Sie Array#reduce die Werte in eine Map zu sammeln, dann verwenden Map#values, und die Ausbreitung Syntax zu konvertieren zurück in ein Array:

const array = [{"label":"Sort-01","data":[{"label":"OCT-2017","weight":2304},{"label":"NOV-2017","weight":1783}]},{"label":"Sort-02","data":[{"label":"OCT-2017","weight":4785},{"label":"NOV-2017","weight":102}]}]; 
 

 
const result = [... // spread the values iterator to an array 
 
    [].concat(...array.map(({ data }) => data)) // map the array into an array of data arrays 
 
    .reduce((m, { label, weight }) => { 
 
    // take item if label exists in map, if not create new 
 
    const item = m.get(label) || { label, weight: 0 }; 
 
    
 
    item.weight += weight; // add the weight 
 
    
 
    return m.set(label, item); // set the item in the map 
 
    }, new Map).values()] // get the values iterator 
 

 
console.log(result);

Hier ist eine spreadless Version:

const array = [{"label":"Sort-01","data":[{"label":"OCT-2017","weight":2304},{"label":"NOV-2017","weight":1783}]},{"label":"Sort-02","data":[{"label":"OCT-2017","weight":4785},{"label":"NOV-2017","weight":102}]}]; 
 

 
const helper = Object.create(null); 
 
const result = [].concat.apply([], array.map(({ data }) => data)) // map the array into an array of data arrays, and flatten by apply concat 
 
    .reduce((r, { label, weight }) => { 
 
    // if label is not in helper, add to helper, and push to r 
 
    if(!helper[label]) { 
 
     helper[label] = { label, weight: 0 }; 
 
     r.push(helper[label]); 
 
    } 
 
    
 
    helper[label].weight += weight; // add the weight to the object 
 
    
 
    return r; 
 
    }, []) // get the values iterator 
 

 
console.log(result);

+0

Gibt es eine Möglichkeit, dies ohne die Ausbreitung zu tun? Ich glaube nicht, dass das Projekt, an dem ich gerade arbeite, die Betreiber bereits verbreitet hat. Ich bekomme eine "[] .concat.apply (...). Reduzieren (...). Werte (...). Scheibe ist keine Funktion" Fehler. – Jay

+0

Ich habe eine andere Version ohne Spread und Map hinzugefügt. –

1

Sie können reduce oder concat (see Ori's answer) verwenden, um ein abgeflachtes Datenarray zu erhalten. Von hier aus geben Sie Ihr Jahr-Label als Schlüssel und Gewicht als Wert. gehen Sie dann zu einem anderen Reduzierer, um Ihre Gewichte nach Monat zu addieren.

const data = [{label: "Sort-01",data: [{label: "OCT-2017",weight: 2304,},{label: "NOV-2017",weight: 1783,},],},{label: "Sort-02",data: [{label: "OCT-2017",weight: 4785,},{label: "NOV-2017",weight: 102,},],},]; 
 
const flatten = (acc, cur) => { 
 
    cur.data.forEach(val => acc.push(val)); 
 
    return acc; 
 
}; 
 
const monthMap = ({ label, weight }) => ({ [label]: weight }); 
 
const reducer = (acc, cur) => { 
 
    const key = Object.keys(cur)[0] 
 
    if (!acc.hasOwnProperty(key)) { acc[key] = 0 } 
 
    acc[key] += cur[key]; 
 
    return acc; 
 
}; 
 

 
let x = data.reduce(flatten, []).map(monthMap).reduce(reducer, {}); 
 
console.log(x);

+0

Funktioniert super danke! – Jay