循环包含其他对象数组的对象数组。并做出一定的计算

时间:2016-12-14 14:57:29

标签: javascript arrays object ecmascript-6

让我解释一下我在说什么。我有以下数组:

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现在找到统计名%的{​​{1}}

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
    	newSold = stat.sold + oldSold.sold // sum
    } else { // don't sum anything
    	newSold = stat.sold
    }
		stat.sold = newSold;
    stat.percentage = `${(newSold / total * 100).toFixed(2)}%`;
    return stat;
  });
  return {
    stats: nextStats,
  };
});

console.log(newStats);

A,B,C。已经走了..

对整件事情有没有更好的方法?我真的不喜欢绘图并获得总数,然后与其他人一起工作..有没有办法做得更好?感谢...

3 个答案:

答案 0 :(得分: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#assignarray 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);




答案 2 :(得分: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))