按键对对象进行分组以供Chartjs条形图使用

4

我正在尝试使用Chart.js创建柱状图。我卡在了尝试基于用户状态创建分组柱状图上。这是数据:

[{statusId: 0, firstName: "Joe", status: "appealed", count: 1},
{statusId: 0, firstName: "Jane", status: "approved", count: 100},
{statusId: 0, firstName: "Smith", status: "approved", count: 63},
{statusId: 0, firstName: "Mike", status: "approved", count: 63},
{statusId: 0, firstName: "Ken", status: "approved", count: 35},
{statusId: 0, firstName: "Kim", status: "approved", count: 193},
{statusId: 0, firstName: "Joe", status: "approved", count: 1},
{statusId: 0, firstName: "Jane", status: "closed", count: 1},
{statusId: 0, firstName: "Joe", status: "concluded", count: 1},
{statusId: 0, firstName: "Jane", status: "denied", count: 6},
{statusId: 0, firstName: "Smith", status: "denied", count: 9},
{statusId: 0, firstName: "Mike", status: "denied", count: 1},
{statusId: 0, firstName: "Mark", status: "denied", count: 8},
{statusId: 0, firstName: "Ken", status: "denied", count: 2},
{statusId: 0, firstName: "Kim", status: "denied", count: 20},
{statusId: 0, firstName: "Joe", status: "denied", count: 2},
{statusId: 0, firstName: "Joe", status: "transferred", count: 1}]

根据这些数据,我需要为用户创建一个图表,其中x轴是用户的每个状态计数。可以通过以下数据集的数组在Chartjs中轻松完成:

datasets:[{
      data: [//some counts for a group],
     },
     {
       data: [// counts for another group],
     }
    // and so on
}]

问题在于我需要根据状态对这些数据进行分组。因此,我能想到的一个解决方案是:
angular.forEeach(data, function(val)){ 
   switch(val.status){
       case 'approved':
        // add count to an approved count array
        break;
       case 'appealed':
       // add count to appealed count array
       break;
   }

}

我认为这里存在问题。如果他们创建了另一个状态,例如“pending”,那么我就必须回去更改代码。有没有办法通过状态分组对象并创建每个组的计数数据数组,然后将其用于数据集?

我刚刚在Pluralsight上报名了JavaScript课程,所以学习高级JavaScript还需要一段时间。在此期间,有人可以向我展示解决这个难题的正确且有效的方法吗?

例子

Chart.js 要求数据格式如下:

var data = {
    labels: ['Joe', 'Jane', 'Smith', 'Mike', 'Ken', 'Kim', 'Mark'],
    datasets: [
        {
            label: 'Appealed',
            fillColor: '#382765',
            data: [1,0,0,0,0,0,0]
        },
        {
            label: 'Approved',
            fillColor: '#7BC225',
            data: [1, 100, 63, 63, 35, 193,0]
        },
        {
            label: 'Denied',
            fillColor: '#2196F3',
            data: [2, 6, 9, 1, 2, 20, 8]
        },

    ]

}

所以,这里发生的是针对labels中的每个itemdatasets数组内部的data数组中有statuslabelcount。例如:对于Appealedlabeldata数组:1Joeappealed计数,其余用户的计数为0。

数据集的数据是否有顺序,还是与给定数据相同?数据是否按状态排序? - Nina Scholz
它与给定的数据相同。如果有帮助的话,我可以按状态或任何其他标准进行排序。 - Kuni
1
如果我正确理解了您的问题,您可以使用Lodash的groupBy函数。 - neptune
1个回答

6
你可以使用哈希表作为与相同status的数组的参考,另外使用另一个哈希表来存储名称的索引。然后构建标签数组和数据集。

var raw = [{ statusId: 0, firstName: "Joe", status: "appealed", count: 1 }, { statusId: 0, firstName: "Jane", status: "approved", count: 100 }, { statusId: 0, firstName: "Smith", status: "approved", count: 63 }, { statusId: 0, firstName: "Mike", status: "approved", count: 63 }, { statusId: 0, firstName: "Ken", status: "approved", count: 35 }, { statusId: 0, firstName: "Kim", status: "approved", count: 193 }, { statusId: 0, firstName: "JoeJoe", status: "approved", count: 1 }, { statusId: 0, firstName: "Jane", status: "closed", count: 1 }, { statusId: 0, firstName: "Joe", status: "concluded", count: 1 }, { statusId: 0, firstName: "Jane", status: "denied", count: 6 }, { statusId: 0, firstName: "Smith", status: "denied", count: 9 }, { statusId: 0, firstName: "Mike", status: "denied", count: 1 }, { statusId: 0, firstName: "Mark", status: "denied", count: 8 }, { statusId: 0, firstName: "Ken", status: "denied", count: 2 }, { statusId: 0, firstName: "Kim", status: "denied", count: 20 }, { statusId: 0, firstName: "Joe", status: "denied", count: 2 }, { statusId: 0, firstName: "Joe", status: "transferred", count: 1 }],
    nameIndices = Object.create(null),
    statusHash = Object.create(null),
    data = { labels: [], datasets: [] };

raw.forEach(function (o) {
    if (!(o.firstName in nameIndices)) {
        nameIndices[o.firstName] = data.labels.push(o.firstName) - 1;
        data.datasets.forEach(function (a) { a.data.push(0); });
    }
    if (!statusHash[o.status]) {
        statusHash[o.status] = { label: o.status, fillcolor: 'f00', data: data.labels.map(function () { return 0; }) };
        data.datasets.push(statusHash[o.status]);
    }
    statusHash[o.status].data[nameIndices[o.firstName]] = o.count;
});

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


哇,这真是太快了!看起来就是我需要的。我正在阅读代码并从中学习。我将把它应用到我的应用程序中,看看是否还有更多问题。一旦我理解了所有内容,我会将其标记为答案。这太棒了!! - Kuni
实际上,这并不是我预期的结果。事实证明,尽管它以我需要的格式提供给我,但它与“firstName”不匹配。我一直在努力解决这个问题。你能帮我找出问题吗?图表应该在x轴上有“firstname”。因此,数据集数组的长度应该等于用户数量。他们的状态和计数应该在该对象内。 - Kuni
所以,独特的“firstname”应该在“datasets”数组之外的“legends”数组中,如果我的意思表达清楚的话。 - Kuni
请在示例中添加所需的数据。 - Nina Scholz
我在原问题中添加了示例。 - Kuni
做到了,我明白你的意思。我会再读一下.map()函数,看起来很有用。谢谢。 - Kuni

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接