聚合和转换对象数组

Aggregate and transform array of objects

使用javascript函数式编程方法(如map/reduce),如何aggregate/countarr1status字段并将其转换为数组arr2 中的 key/value 个对象。

arr1 = [
  {'task':'do something 1', 'status':'done'} , 
  {'task':'do something 2', 'status':'done'} , 
  {'task':'do something 3', 'status':'pending'} , 
  {'task':'do something 4', 'status':'done'}
];

// Aggregate arr1 `status` field and transform to:

arr2 = [
  {key:'done', value: 3},
  {key:'pending', value: 1}
];

这是我的 WIP 部分 解决方案,它 处理聚合部分。我仍然需要转换部分。

var arr2 = arr1.map(function(item) {
    return item.status;
  }).reduce(function(acc,curr,idx){
    if(acc[curr] === undefined) acc[curr] = 1;
    else acc[curr] += 1;
    return acc;
  }, []); 

你可以试试Array.prototype.forEach()。也可以不使用数组,而是使用对象。这将避免您循环查找特定状态的计数。

arr1 = [
  {'task':'do something 1', 'status':'done'} , 
  {'task':'do something 2', 'status':'done'} , 
  {'task':'do something 3', 'status':'pending'} , 
  {'task':'do something 4', 'status':'done'}
];

var result = {};
arr1.forEach(function(item){
  if(!result[item.status])
    result[item.status] = 0;
  
  result[item.status]++;
});
console.log(result);

这是我能想到的最实用的方法。这包括聚合和您想要的转换:

var arr2 = Object.keys(arr2 = arr1.map(function(item) {
    return item.status;
}).reduce(function(acc,curr){
    acc[curr] = acc[curr] + 1 || 1;
    return acc;
}, [])).map(function(item){
    return {key: item, value: arr2[item]}
});

由于您将输出值存储为数组,因此您应该检查密钥状态是否存在。如果存在则增加其值。

arr2 = [];
arr1.forEach(function(item){
  var keyPresent = false;
  for(var i = 0, len = arr2.length; i < len; i++) {
      if( arr2[ i ].key === item.status ){
         keyPresent = true;
         arr2[ i ].value++
      }
  }
  if(!keyPresent){
    arr2.push({key: item.status , value : 1})
}

给出的输出
arr2 = [
  {key:'done', value: 3},
  {key:'pending', value: 1}
];