【问题标题】: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?如何循环遍历对象对象和对象数组并根据匹配数组元素的计数更新嵌套对象值?
【发布时间】:2021-11-07 02:39:56
【问题描述】:

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

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,它获取整个 dataArr 中每个状态的总计数,准备好或退休,并将其应用于每个服务对象:

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


【问题讨论】:

    标签: javascript arrays data-structures reduce


    【解决方案1】:

    你可以使用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; }

    【讨论】:

    • 就我而言,未来状态可能会发生变化,包括新状态,因此我动态配置了该状态计数对象。工作得很好,将研究减少更多。谢谢!
    • 想知道您是否可以提供一些见解。替换时 if (!acc[service]) acc[service] = { 就绪:0,退休:0 };使用 if (!acc[service]) acc[service] = nestedObj;,计数现在关闭,结果现在与我发布的最后一个 obj 代码块相同。这有什么原因吗?考虑到nestedObj 也{准备好:0,退休:0},有点困惑。
    • @KaliaHayes 这里的nestedObj 是什么?
    • 如果您将其分配为(!acc[service]) acc[servi,那么您总是在分配一个新对象,但如果存在键acc[service],则必须更新值。
    • 感谢您的反馈。我已经更新了我的代码以包含nestedObj 的浅拷贝; let statusCountObj = Object.assign({}, nestedObj); if (!acc[service]) acc[service] = statusCountObj; 运行良好。再次感谢您!
    猜你喜欢
    • 2020-02-21
    • 1970-01-01
    • 2021-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多