2016-12-14 6 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)です。それを2回することはまだ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

単一のアレイにすべての統計情報を組み合わせることObject#assignArray#mapを使用し、array spread。合計を得るにはArray#reduceを使用してください。 flatlist地図、そしてtemplate literalを使用して、各STATにパーセンテージを割り当てます

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

を使用して機能に束ね別のアプローチだです
関連する問題