Kontrollierte Antwort - nur oberflächliche Gruppierung. Es ist ziemlich gut zu verstehen, zu reduzieren. Frage bieten auch das Problem der zusätzlichen aggregierten Berechnungen.
Hier ist ein REAL GROUP BY für ein Array von Objekten nach einem oder mehreren Feldern mit 1) berechneten Schlüsselnamen und 2) einer vollständigen Lösung für die Kaskadierung der Gruppierung durch Bereitstellung der Liste der gewünschten Schlüssel und Konvertierung der eindeutigen Werte in Wurzelschlüssel wie bei SQL GROUP BY tut.
const inputArray = [
{ Phase: "Phase 1", Step: "Step 1", Task: "Task 1", Value: "5" },
{ Phase: "Phase 1", Step: "Step 1", Task: "Task 2", Value: "10" },
{ Phase: "Phase 1", Step: "Step 2", Task: "Task 1", Value: "15" },
{ Phase: "Phase 1", Step: "Step 2", Task: "Task 2", Value: "20" },
{ Phase: "Phase 2", Step: "Step 1", Task: "Task 1", Value: "25" },
{ Phase: "Phase 2", Step: "Step 1", Task: "Task 2", Value: "30" },
{ Phase: "Phase 2", Step: "Step 2", Task: "Task 1", Value: "35" },
{ Phase: "Phase 2", Step: "Step 2", Task: "Task 2", Value: "40" }
];
var outObject = inputArray.reduce(function(a, e) {
// GROUP BY estimated key (estKey), well, may be a just plain key
// a -- Accumulator result object
// e -- sequentally checked Element, the Element that is tested just at this itaration
// new grouping name may be calculated, but must be based on real value of real field
let estKey = (e['Phase']);
(a[estKey] ? a[estKey] : (a[estKey] = null || [])).push(e);
return a;
}, {});
console.log(outObject);
Spielen mit estKey
-- Sie können nach mehr als einem Feld gruppieren, zusätzliche Aggregationen, Berechnungen oder andere Verarbeitungen hinzufügen.
Sie können Daten auch rekursiv gruppieren. Zum Beispiel zunächst gruppieren nach Phase
, dann durch Step
Feld und so weiter. Zusätzlich abblasen die fetten Restdaten.
const inputArray = [
{ Phase: "Phase 1", Step: "Step 1", Task: "Task 1", Value: "5" },
{ Phase: "Phase 1", Step: "Step 1", Task: "Task 2", Value: "10" },
{ Phase: "Phase 1", Step: "Step 2", Task: "Task 1", Value: "15" },
{ Phase: "Phase 1", Step: "Step 2", Task: "Task 2", Value: "20" },
{ Phase: "Phase 2", Step: "Step 1", Task: "Task 1", Value: "25" },
{ Phase: "Phase 2", Step: "Step 1", Task: "Task 2", Value: "30" },
{ Phase: "Phase 2", Step: "Step 2", Task: "Task 1", Value: "35" },
{ Phase: "Phase 2", Step: "Step 2", Task: "Task 2", Value: "40" }
];
/**
* Small helper to get SHALLOW copy of obj WITHOUT prop
*/
const rmProp = (obj, prop) => ( (({[prop]:_, ...rest})=>rest)(obj) )
/**
* Group Array by key. Root keys of a resulting array is value
* of specified key.
*
* @param {Array} src The source array
* @param {String} key The by key to group by
* @return {Object} Object with grouped objects as values
*/
const grpBy = (src, key) => src.reduce((a, e) => (
(a[e[key]] = a[e[key]] || []).push(rmProp(e, key)), a
), {});
/**
* Collapse array of object if it consists of only object with single value.
* Replace it by the rest value.
*/
const blowObj = obj => Array.isArray(obj) && obj.length === 1 && Object.values(obj[0]).length === 1 ? Object.values(obj[0])[0] : obj;
/**
* Recursive grouping with list of keys. `keyList` may be an array
* of key names or comma separated list of key names whom UNIQUE values will
* becomes the keys of the resulting object.
*/
const grpByReal = function (src, keyList) {
const [key, ...rest] = Array.isArray(keyList) ? keyList : String(keyList).trim().split(/\s*,\s*/);
const res = key ? grpBy(src, key) : [...src];
if (rest.length) {
for (const k in res) {
res[k] = grpByReal(res[k], rest)
}
} else {
for (const k in res) {
res[k] = blowObj(res[k])
}
}
return res;
}
console.log( JSON.stringify( grpByReal(inputArray, 'Phase, Step, Task'), null, 2 ) );