2017-10-18 73 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