逐行对对象中的每一行求和

时间:2017-12-13 12:07:15

标签: javascript arrays reactjs ecmascript-6

我需要将minutesseconds_left加起来并按id_project分组。

0: {id_project: 2, minutes: 12, seconds_left: NaN}
1: {id_project: 3, minutes: 15, seconds_left: 11}
2: {id_project: 4, minutes: 0, seconds_left: 11}
3: {id_project: 5, minutes: 0, seconds_left: 2}
4: {id_project: 0, minutes: 0, seconds_left: NaN}
5: {id_project: 1, minutes: 0, seconds_left: NaN}
6: {id_project: 4, minutes: 200, seconds_left: 6}
7: {id_project: 6, minutes: 43, seconds_left: NaN}
8: {id_project: 5, minutes: 100, seconds_left: NaN}
9: {id_project: 2, minutes: 123, seconds_left: NaN}
10: {id_project: 3, minutes: 454, seconds_left: NaN}
11: {id_project: 2, minutes: 89, seconds_left: NaN}
12: {id_project: 5, minutes: 23, seconds_left: NaN}
13: {id_project: 4, minutes: 0, seconds_left: NaN}
14: {id_project: 4, minutes: 11, seconds_left: NaN}
15: {id_project: 3, minutes: 66, seconds_left: NaN}
16: {id_project: 1, minutes: 676, seconds_left: NaN}

我想到了地图&减少,但我不能这样做。

我的问题有解决办法吗?

感谢您的回答:)

4 个答案:

答案 0 :(得分:1)

首先关闭所有沟渠NaN或在执行前将它们转换为0,否则算术将全部具有NaN值。 现在这就是我所做的:我创建了一个函数来将您的数组映射到具有唯一项目ID的新对象,其中每个都具有分钟和秒的总和:

var arr = [
    { id_project: 2, minutes: 12, seconds_left: 1 },
    { id_project: 3, minutes: 15, seconds_left: 11 },
    { id_project: 4, minutes: 0, seconds_left: 11 },
    { id_project: 5, minutes: 0, seconds_left: 2 },
    { id_project: 0, minutes: 0, seconds_left: 2 },
    { id_project: 1, minutes: 0, seconds_left: 3 },
    { id_project: 4, minutes: 200, seconds_left: 6 },
    { id_project: 6, minutes: 43, seconds_left: 3 },
    { id_project: 5, minutes: 100, seconds_left: 3 },
    { id_project: 2, minutes: 123, seconds_left: 10 },
    { id_project: 3, minutes: 454, seconds_left: 2 },
    { id_project: 2, minutes: 89, seconds_left: 2 },
    { id_project: 5, minutes: 23, seconds_left: 3 },
    { id_project: 4, minutes: 0, seconds_left: 4 },
    { id_project: 3, minutes: 66, seconds_left: 5 },
    { id_project: 1, minutes: 676, seconds_left: 5 }
];

var _flatten = function (arr) {
    var struct = {}; // We'll use a new flattened structure.
    var len = arr.length;
    for (var i = 0; i < len; i++) {
        var pID = arr[i].id_project;
        if (undefined !== struct[pID] && null !== struct[pID]) {
            // Already assigned. Sum minutes and seconds to already existing values.
            struct[pID].sum =
                struct[pID].sum +
                (arr[i].minutes * 60) +
                arr[i].seconds_left;
        }
        else {
            // Current project ID has not been assigne to new structure. Assign.
            struct[pID] = { sum: (arr[i].minutes * 60) + arr[i].seconds_left };
        }
    }
    return struct;
}

输出(总和以秒为单位):

_flatten(arr);

0 : {sum: 2}
1 : {sum: 40568}
2 : {sum: 13453}
3 : {sum: 32118}
4 : {sum: 12021}
5 : {sum: 7388}
6 : {sum: 2583}

答案 1 :(得分:1)

您可以将哈希表作为对具有相同id_project的对象的引用,并收集结果的所有值。

&#13;
&#13;
var array = [{ id_project: 2, minutes: 12, seconds_left: NaN }, { id_project: 3, minutes: 15, seconds_left: 11 }, { id_project: 4, minutes: 0, seconds_left: 11 }, { id_project: 5, minutes: 0, seconds_left: 2 }, { id_project: 0, minutes: 0, seconds_left: NaN }, { id_project: 1, minutes: 0, seconds_left: NaN }, { id_project: 4, minutes: 200, seconds_left: 6 }, { id_project: 6, minutes: 43, seconds_left: NaN }, { id_project: 5, minutes: 100, seconds_left: NaN }, { id_project: 2, minutes: 123, seconds_left: NaN }, { id_project: 3, minutes: 454, seconds_left: NaN }, { id_project: 2, minutes: 89, seconds_left: NaN }, { id_project: 5, minutes: 23, seconds_left: NaN }, { id_project: 4, minutes: 0, seconds_left: NaN }, { id_project: 4, minutes: 11, seconds_left: NaN }, { id_project: 3, minutes: 66, seconds_left: NaN }, { id_project: 1, minutes: 676, seconds_left: NaN }],
    temp = {},
    result = [];

array.forEach(function (o) {
    if (!temp[o.id_project]) {
        temp[o.id_project] = { id_project: o.id_project, minutes: 0, seconds_left: 0 };
        result.push(temp[o.id_project]);
    }
    temp[o.id_project].minutes += o.minutes || 0;
    temp[o.id_project].seconds_left += o.seconds_left || 0;
});

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

答案 2 :(得分:0)

如果可以遍历此数组,请创建一个包含数组总和的新对象

像这样的东西

var myArray = [{id_project: 2, minutes: 12, seconds_left: 30},{id_project: 2, minutes: 12, seconds_left: 50},{id_project: 3, minutes: 12, seconds_left: 12}]
var result = {};
myArray.forEach(function (element) {
  if (!result.hasOwnProperty(element.id_project))
    result[element.id_project] = {minutes : 0, seconds_left : 0};
  result[element.id_project].minutes += element.minutes;
  result[element.id_project].seconds_left += element.seconds_left;
});
    
console.log(result);

答案 3 :(得分:0)

以下是你要求的,你可以使用map和reduce。我只使用map替换NaN为0并减少两次,一次获得总秒数,一次创建小时,分钟,秒对象:

var tmpTotal = [
  {id_project: 2, minutes: 12, seconds_left: NaN}
  ,{id_project: 3, minutes: 15, seconds_left: 11}
  ,{id_project: 4, minutes: 0, seconds_left: 11}
  ,{id_project: 5, minutes: 0, seconds_left: 2}
  ,{id_project: 0, minutes: 0, seconds_left: NaN}
  ,{id_project: 1, minutes: 0, seconds_left: NaN}
  ,{id_project: 4, minutes: 200, seconds_left: 6}
  ,{id_project: 6, minutes: 43, seconds_left: NaN}
  ,{id_project: 5, minutes: 100, seconds_left: NaN}
  ,{id_project: 2, minutes: 123, seconds_left: NaN}
  ,{id_project: 3, minutes: 454, seconds_left: NaN}
  ,{id_project: 2, minutes: 89, seconds_left: NaN}
  ,{id_project: 5, minutes: 23, seconds_left: NaN}
  ,{id_project: 4, minutes: 0, seconds_left: NaN}
  ,{id_project: 4, minutes: 11, seconds_left: NaN}
  ,{id_project: 3, minutes: 66, seconds_left: NaN}
  ,{id_project: 1, minutes: 676, seconds_left: NaN}
]
.map(//set seconds_left to 0 when NaN
  item=>
    isNaN(item.seconds_left)
      ? Object.assign({},item,{seconds_left:0})
      : item
)
.reduce(//group totals by id
  (acc,item)=>{
    acc[item.id_project]=acc[item.id_project] || {sum:0};
    acc[item.id_project].sum = 
      acc[item.id_project].sum + item.minutes * 60;
    acc[item.id_project].sum = 
      acc[item.id_project].sum + item.seconds_left;
    return acc;
  }
  ,{}
);
console.log(
  JSON.stringify(
    Object.keys(tmpTotal)//create hours,minutes,seconds from sum object
    .reduce(
      (acc,key)=>{
        acc[key] = {
          hours: Math.floor(tmpTotal[key].sum/3600),
          minutes: Math.floor((tmpTotal[key].sum%3600)/60),
          seconds: tmpTotal[key].sum%60
        }
        return acc;
      }
      ,{}
    )
    ,undefined
    ,2
  )
);