2016-12-14 57 views
2

讓我解釋一下我在說什麼。我有以下陣列:在包含其他對象數組的對象數組上循環。並做出一定的計算

const days = [ 
{ 

    date: '2016-12-13T00:00:00.000Z', 
    stats: [ 
     { name: 'A', sold: 34, }, 
     { name: 'B', sold: 3, }, 
     { name: 'C', sold: 26, }, 
    ], 
    }, 
    { 
    date: '2016-12-14T00:00:00.000Z', 
    stats: [ 
     { name: 'D', sold: 34, }, 
     { name: 'E', sold: 3, }, 
     { name: 'F', sold: 26, }, 
    ], 
    }, 
    { 
    date: '2016-12-14T00:00:00.000Z', 
    stats: [ 
     { name: 'D', sold: 34, }, 
     { name: 'E', sold: 3, }, 
     { name: 'F', sold: 26, }, 
    ], 
    }, 
]; 

我想要做的就是找到每個stat.name因此,例如百分比。如果我們將所有銷售的價值,我們得到:189現在發現STAT名B

(3/189) * 100 

%哪位能給我:1.58%這代表出售物品類別的%

理想的結果後,我是這樣的:

const result = [ 
    { name: 'A', sold: 34, percentage: '17,98%' }, 
    { name: 'B', sold: 3, percentage: '1,58%', }, 
    { name: 'C', sold: 26, percentage: '13,75%', }, 
    { name: 'D', sold: 68, percentage: '35,97%', }, 
    { name: 'E', sold: 6, percentage: '3,17%' }, 
    { name: 'F', sold 52, percentage: '27,51%' }, 
]; 

我做了什麼至今:

const days = [ 
 
{ 
 
    date: '2016-12-13T00:00:00.000Z', 
 
    stats: [ 
 
     { name: 'A', sold: 34, }, 
 
     { name: 'B', sold: 3, }, 
 
     { name: 'C', sold: 26, }, 
 
    ], 
 
    }, 
 
    { 
 
    date: '2016-12-14T00:00:00.000Z', 
 
    stats: [ 
 
     { name: 'D', sold: 34, }, 
 
     { name: 'E', sold: 3, }, 
 
     { name: 'F', sold: 26, }, 
 
    ], 
 
    }, 
 
    { 
 
    date: '2016-12-14T00:00:00.000Z', 
 
    stats: [ 
 
     { name: 'D', sold: 34, }, 
 
     { name: 'E', sold: 3, }, 
 
     { name: 'F', sold: 26, }, 
 
    ], 
 
    }, 
 
]; 
 

 
let total = 0; 
 
days.map(record => record.stats.map(category => total += category.sold)); // save the total; 
 

 
const newStats = days.reduce(function (pastDay, currentDay) { 
 
    const nextStats = currentDay.stats.map(function(stat) { 
 
    const oldSold = pastDay.stats.find((old) => old.name === stat.name); // object that match by name. 
 
    let newSold; 
 
    if (oldSold) { // if matched 
 
    \t newSold = stat.sold + oldSold.sold // sum 
 
    } else { // don't sum anything 
 
    \t newSold = stat.sold 
 
    } 
 
\t \t stat.sold = newSold; 
 
    stat.percentage = `${(newSold/total * 100).toFixed(2)}%`; 
 
    return stat; 
 
    }); 
 
    return { 
 
    stats: nextStats, 
 
    }; 
 
}); 
 

 
console.log(newStats);

其中outsputs:

{ 
    "stats": [ 
    { 
     "name": "D", 
     "sold": 68, 
     "percentage": "35.98%" 
    }, 
    { 
     "name": "E", 
     "sold": 6, 
     "percentage": "3.17%" 
    }, 
    { 
     "name": "F", 
     "sold": 52, 
     "percentage": "27.51%" 
    } 
    ] 
} 

A,B,C都不見了..

有沒有更好的方法來處理整件事情?我真的不喜歡映射和獲得總數,然後與其他人一起工作..有沒有辦法做得更好?謝謝...

+0

我只是使用一個好的老式循環來計算所有的和。然後循環結果來完成百分比。數組上的循環是O(n)。做兩次還只是O(n)。 –

回答

3

您可以先收集已售出的數量,然後用百分比呈現數組。

var days = [{ date: '2016-12-13T00:00:00.000Z', stats: [{ name: 'A', sold: 34, }, { name: 'B', sold: 3, }, { name: 'C', sold: 26, }, ], }, { date: '2016-12-14T00:00:00.000Z', stats: [{ name: 'D', sold: 34, }, { name: 'E', sold: 3, }, { name: 'F', sold: 26, }, ], }, { date: '2016-12-14T00:00:00.000Z', stats: [{ name: 'D', sold: 34, }, { name: 'E', sold: 3, }, { name: 'F', sold: 26, }, ], }, ], 
 
    temp = Object.create(null), 
 
    result = [], 
 
    total = 0; 
 

 
days.forEach(function (day) { 
 
    day.stats.forEach(function (stat) { 
 
     total += stat.sold; 
 
     temp[stat.name] = (temp[stat.name] || 0) + stat.sold; 
 
    }); 
 
}, Object.create(null)); 
 

 
result = Object.keys(temp).map(function (k) { 
 
    return { name: k, sold: temp[k], percentage: (temp[k] * 100/total).toFixed(2) + '%' }; 
 
}); 
 

 
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

+1

謝謝妮娜!這將是最容易理解的方法:) –

1

使用Array#mapObject#assign,並array spread所有屬性結合起來,單個陣列。使用Array#reduce來獲得總和。地圖的flatlist,並使用template literal分配的百分比給每個統計:

const days = [{"date":"2016-12-13T00:00:00.000Z","stats":[{"name":"A","sold":34},{"name":"B","sold":3},{"name":"C","sold":26}]},{"date":"2016-12-14T00:00:00.000Z","stats":[{"name":"D","sold":34},{"name":"E","sold":3},{"name":"F","sold":26}]},{"date":"2016-12-14T00:00:00.000Z","stats":[{"name":"D","sold":34},{"name":"E","sold":3},{"name":"F","sold":26}]}]; 
 
     
 
// flatten the lists 
 
const flatList = [].concat([], ...days.map(({ stats }) => stats)); 
 
    
 
// get the sum 
 
const sum = flatList.reduce((sum, { sold }) => sum + sold, 0); 
 

 
// assign the percentage to each 
 
const result = flatList.map((stat) => Object.assign({}, stat, { percentage: `${(stat.sold/sum * 100).toFixed(2)}%` })); 
 
      
 
console.log(result);

1

我會強烈建議你到一些通用的功能添加到抽象掉了一些複雜性在這裏。有很多方法可以做到這一點,但我會把它作爲一個練習。如果我有更多時間,今天晚些時候我可能會更新答案。

下面是使用Array.prototype.reduce

const days = [ { date: '2016-12-13T00:00:00.000Z', stats: [ { name: 'A', sold: 34, }, { name: 'B', sold: 3, }, { name: 'C', sold: 26, }, ], }, { date: '2016-12-14T00:00:00.000Z', stats: [ { name: 'D', sold: 34, }, { name: 'E', sold: 3, }, { name: 'F', sold: 26, }, ], }, { date: '2016-12-14T00:00:00.000Z', stats: [ { name: 'D', sold: 34, }, { name: 'E', sold: 3, }, { name: 'F', sold: 26, } ] } ] 
 

 
const makeSalesReport = days => { 
 
    let {map,sum} = days 
 
    .reduce((acc, {stats}) => [...acc, ...stats], []) 
 
    .reduce(({map, sum}, {name, sold}) => ({ 
 
     map: map.set(name, map.has(name) ? map.get(name) + sold : sold), 
 
     sum: sum + sold 
 
    }), {map: new Map(), sum: 0}) 
 

 
    return Array.from(map, ([name, sold]) => 
 
    ({name, sold, percentage: sold/sum * 100})) 
 
} 
 
     
 
console.log(makeSalesReport(days))

下面是使用for-of循環

const days = [ { date: '2016-12-13T00:00:00.000Z', stats: [ { name: 'A', sold: 34, }, { name: 'B', sold: 3, }, { name: 'C', sold: 26, }, ], }, { date: '2016-12-14T00:00:00.000Z', stats: [ { name: 'D', sold: 34, }, { name: 'E', sold: 3, }, { name: 'F', sold: 26, }, ], }, { date: '2016-12-14T00:00:00.000Z', stats: [ { name: 'D', sold: 34, }, { name: 'E', sold: 3, }, { name: 'F', sold: 26, } ] } ] 
 

 
const makeSalesReport = days => { 
 
    let map = new Map(), sum = 0 
 
    for (let {stats} of days) { 
 
    for (let {name, sold} of stats) { 
 
     map.set(name, map.has(name) ? map.get(name) + sold : sold), 
 
     sum += sold 
 
    } 
 
    } 
 
    return Array.from(map, ([name, sold]) => 
 
    ({name, sold, percentage: sold/sum * 100})) 
 
} 
 

 
console.log(makeSalesReport(days))

很好地捆綁在功能的另一種方法一種方法