对数组中的值进行分组和计数

时间:2017-06-06 10:33:48

标签: javascript arrays

我有一个包含对象的数组,如下所示。

b = {
  "issues": [{
    "fields": {
      "status": {
        "id": "200",
        "name": "Backlog"
      }
    }
  }, {
    "fields": {
      "status": {
        "id": "202",
        "name": "close"
      }
    }
  }, {
    "fields": {
      "status": {
        "id": "201",
        "name": "close"
      }
    }
  }]
};

我想计算有多少问题的状态为close,有多少问题有backlog。我想将计数保存在一个新的数组中,如下所示。

a = [
  {Name: 'Backlog', count: 1},
  {Name: 'close', count: 2}
];

我尝试了以下内容。

b.issues.forEach(function(i) {
  var statusName = i.fields.status.name;

  if (statusName in a.Name) {
    a.count = +1;
  } else {
    a.push({
      Name: statusName,
      count: 1
    });
  }
});
然而,这似乎不起作用。我该如何实现呢?

4 个答案:

答案 0 :(得分:20)

这是使用Array#reduce的绝佳机会。该函数将采用一个按顺序应用于数组的所有元素的函数,并可用于累积值。我们可以使用它来累积具有各种计数的对象。

为了简化操作,我们只需{name: count, otherName: otherCount}跟踪对象中的计数。对于每个元素,我们检查是否已有name的条目。如果没有,请创建一个计数为0的计数器。否则,递增计数。在reduce之后,我们可以map存储为keys of the object的密钥数组,采用问题中描述的格式。见下文。



var b = {
  "issues": [{
    "fields": {
      "status": {
        "id": "200",
        "name": "Backlog"
      }
    }
  }, {
    "fields": {
      "status": {
        "id": "202",
        "name": "close"
      }
    }
  }, {
    "fields": {
      "status": {
        "id": "201",
        "name": "close"
      }
    }
  }]
};

var counts = b.issues.reduce((p, c) => {
  var name = c.fields.status.name;
  if (!p.hasOwnProperty(name)) {
    p[name] = 0;
  }
  p[name]++;
  return p;
}, {});

console.log(counts);

var countsExtended = Object.keys(counts).map(k => {
  return {name: k, count: counts[k]}; });

console.log(countsExtended);

.as-console-wrapper {
  max-height: 100% !important;
}




备注

  1. Array#reduce不会修改原始数组。
  2. 您可以轻松修改传递给reduce的函数,例如通过更改

    来区分Backlogbacklog
    var name = c.fields.status.name;
    

    var name = c.fields.status.name.toLowerCase();
    
    例如,

    。还可以轻松实现更高级的功能。

答案 1 :(得分:2)

使用ES6箭头功能,您可以使用最少的语法

var b = {
    "issues": [{
        "fields": {
            "status": {
                "id": "200",
                "name": "Backlog"
            }
        }
    }, {
        "fields": {
            "status": {
                "id": "202",
                "name": "close"
            }
        }
    }, {
        "fields": {
            "status": {
                "id": "201",
                "name": "close"
            }
        }
    }]
};

var countOfBackLog = b.issues.filter(x => {
return x.fields.status.name === "Backlog"
}).length

var countOfClose = b.issues.filter(x => {
return x.fields.status.name === "close"
}).length

a =[{Name: 'Backlog', count : countOfBackLog}, {Name: 'close', count : countOfClose}]

有关箭头功能的更多信息here

答案 2 :(得分:1)

你可以这样写。它是动态的。

var a = {}; 
for(var key in b["issues"]){ 
    if(!a.hasOwnProperty(b["issues"][key].fields.status.name)){
     a[b["issues"][key].fields.status.name] = 1;
    }else{
     a[b["issues"][key].fields.status.name] = a[b["issues"][key].fields.status.name]+1;
    }
}
var c = [];
for(var key1 in a){
   c.push({
   name  : key1,
   count : a[key1]
   });
}

答案 3 :(得分:0)

这样的事情应该可以解决问题。只需迭代数据,保留2个计数器,每个类型的问题数量,最后创建所需的数据格式。在jsfiddle上试一试。

var b = {
    "issues": [{
        "fields": {
            "status": {
                "id": "200",
                "name": "Backlog"
            }
        }
    }, {
        "fields": {
            "status": {
                "id": "202",
                "name": "close"
            }
        }
    }, {
        "fields": {
            "status": {
                "id": "201",
                "name": "close"
            }
        }
    }]
};

var data = [];
for(var issue of b.issues){
    var entryFound = false;
    var tempObj = {
        name: issue.fields.status.name,
        count: 1
    };

    for(var item of data){
        if(item.name === tempObj.name){
        item.count++;
        entryFound = true;
        break;
      }
    }

    if(!entryFound){
        data.push(tempObj);
    }
}
console.log(data);