如何循环遍历对象的对象和对象数组,并根据匹配数组元素的计数更新嵌套对象值?

How can I loop through an Object of Objects and an Array of Objects and update nested object values based on the count of matching array elements?

假设我有一些像这样组织的数据...

dataArr = [
    {service: s1, status: ready},
    {service: s2, status: ready},
    {service: s1, status: retired},
    {service: s3, status: retired},
    {service: s2, status: ready}
]

有 3 种不同的服务。每个数据元素都具有三种服务类型中的一种,并且状态为退役或就绪。

如何循环遍历 dataArr 中的每个元素以创建以下 statusByServiceObj?例如,在所有数据中,我想找到所有s1服务类型,然后确定有多少s1处于退休或就绪状态。

statusByServiceObj = {
    {s1: {ready: 1, retired: 1} },
    {s2: {ready: 2, retired: 0} },
    {s3: {ready: 0, retired: 1} },
}

我目前所在的位置,我已经遍历了 dataArr 数组来创建一个对象,如下所示:

let obj = {};
let nestedObj = {};

dataArr.forEach(ele => {
    obj[ele.service] = nestedObj;
    nestedObj[ele.status] = 0;
});

// obj now equals...
obj = {
    {s1: {ready: 0, retired: 0} },
    {s2: {ready: 0, retired: 0} },
    {s3: {ready: 0, retired: 0} },
}

当循环遍历我的 dataArr 时,我很难根据服务类型填充就绪和停用计数。

对最佳实践建议非常开放,对 JS 不熟悉。我觉得我在应用 0 值时会脑死亡......应该是一种计数。或者可能将对象的对象转换为对象数组...

我尝试像这样按服务计算状态值:

dataArr.forEach(ele => {
    for (let service in obj) {
        let countsObj = obj[service];
        for (let status in countsObj) {
            if (ele.service === service && ele.status === status) {
                countsObj[status = countsObj[status] + 1;
            }
        }
    }
}

然而,obj 上的这个 returns 获取整个 dataArr 中每个状态的总计数,准备就绪或退休,并将其应用于每个服务对象:

obj = {
    {s1: {ready: 3, retired: 2} },
    {s2: {ready: 3, retired: 2} },
    {s3: {ready: 3, retired: 2} },
}


您可以使用reduce来获得想要的结果

const dataArr = [
  { service: "s1", status: "ready" },
  { service: "s2", status: "ready" },
  { service: "s1", status: "retired" },
  { service: "s3", status: "retired" },
  { service: "s2", status: "ready" },
];

const result = dataArr.reduce((acc, curr) => {
  const { service, status } = curr;
  if (!acc[service]) acc[service] = { ready: 0, retired: 0 };
  acc[service][status] += 1;
  return acc;
}, {});

console.log(result);
/* This is not a part of answer. It is just to give the output fill height. So IGNORE IT */
.as-console-wrapper { max-height: 100% !important; top: 0; }