2017-10-18 110 views
1

我目前正在試圖映射和減少函數來展平一個多維數組。
這是一個模擬的示例數據集:減少多維數組

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 
     } 
    ] 
    }, 
...... 
] 

我知道,以通過排序號碼映射簡化我可以使用:

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

不過,我想在這個月,而不是減少排序號碼。
我將不勝感激任何幫助。

感謝,
周杰倫

回答

2

使用陣列#地圖,讓data性質陣列的一個數組,然後用Array#concatspread壓平。使用Array#reduce收集值轉換爲Map,然後用Map#values,並蔓延語法轉換回一個數組:

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

這裏是一個spreadless版本:

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

有沒有辦法做到這一點不蔓延?我不認爲我目前正在開展的項目已經擴大了運營商的範圍。我得到一個「[] .concat.apply(...)。reduce(...)。values(...)。slice不是函數」錯誤。 – Jay

+0

我添加了另一個沒有傳播的版本和Map。 –

1

您可以使用reduce或concat (see Ori's answer)來獲取展平的數據數組。從那裏重新分配你的年份標籤作爲價值的關鍵和重量。 然後傳遞給另一個減速器,以按月總計您的重量。

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

非常感謝你! – Jay