javascript - 从 json 层次结构中较低的键嵌套或映射数据

标签 javascript arrays json d3.js

我需要重新组织我的 json 数据,使其基于当前嵌套在数据中两层以下的键。数据带有基于事件的“id”、“name”等的层次结构。我需要将层次结构基于“年”,它位于每个项目的“年”数组中。我尝试了各种方法,但我什至不确定我是否应该使用 d3.nest 或 d3.map(或两者)。

我没有费心发布我的 d3 代码,因为我在这个阶段所做的就是加载数据并将其记录到控制台。

非常感谢任何帮助。

传入的数据:

[{
    "id": 2,
    "name": "Test activity 51",
    "code": "D51",
    "description": "Description goes here.",
    "years": [{
        "id": 8,
        "year": "2020-2021",
        "target": 65,
        "weeks": [{
            "week_ending": "2020-12-06",
            "hours": 4.0
        }, {
            "week_ending": "2020-12-06",
            "hours": 2.5
        }, {
            "week_ending": "2020-10-18",
            "hours": 2.0
        }, {
            "week_ending": "2020-07-19",
            "hours": 2.0
        }]
    }, {
        "id": 11,
        "year": "2019-2020",
        "target": 40,
        "weeks": [{
            "week_ending": "2020-01-05",
            "hours": 3.0
        }, {
            "week_ending": "2019-09-15",
            "hours": 5.5
        }, {
            "week_ending": "2019-07-14",
            "hours": 1.5
        }]
    }, {
        "id": 10,
        "year": "2018-2019",
        "target": 40,
        "weeks": [{
            "week_ending": "2018-09-30",
            "hours": 3.0
        }]
    }]
}, {
    "id": 3,
    "name": "Test activity 63",
    "code": "D63",
    "description": null,
    "years": [{
        "id": 2,
        "year": "2019-2020",
        "target": 15,
        "weeks": [{
            "week_ending": "2020-05-24",
            "hours": 2.0
        }, {
            "week_ending": "2020-03-22",
            "hours": 4.0
        }, {
            "week_ending": "2020-01-26",
            "hours": 5.0
        }, {
            "week_ending": "2020-01-19",
            "hours": 4.0
        }, {
            "week_ending": "2019-12-01",
            "hours": 4.5
        }, {
            "week_ending": "2019-08-25",
            "hours": 2.0
        }, {
            "week_ending": "2019-07-21",
            "hours": 3.0
        }]
    }, {
        "id": 9,
        "year": "2018-2019",
        "target": 30,
        "weeks": [{
            "week_ending": "2018-08-19",
            "hours": 3.5
        }, {
            "week_ending": "2019-02-10",
            "hours": 5.0
        }, {
            "week_ending": "2018-12-30",
            "hours": 3.0
        }, {
            "week_ending": "2018-10-21",
            "hours": 2.0
        }, {
            "week_ending": "2018-08-26",
            "hours": 4.0
        }]
    }]
}, {
    "id": 1,
    "name": "Test activity 27",
    "code": "D27",
    "description": "Description goes here.",
    "years": [{
        "id": 4,
        "year": "2019-2020",
        "target": 30,
        "weeks": [{
            "week_ending": "2020-04-05",
            "hours": 2.0
        }, {
            "week_ending": "2020-03-22",
            "hours": 6.0
        }, {
            "week_ending": "2020-01-12",
            "hours": 1.0
        }]
    }, {
        "id": 1,
        "year": "2018-2019",
        "target": 25,
        "weeks": [{
            "week_ending": "2018-11-18",
            "hours": 6.0
        }, {
            "week_ending": "2018-10-21",
            "hours": 2.0
        }, {
            "week_ending": "2018-10-07",
            "hours": 6.0
        }]
    }]
}, {
    "id": 10,
    "name": "Test activity 59",
    "code": "D59",
    "description": null,
    "years": [{
        "id": 13,
        "year": "2020-2021",
        "target": 15,
        "weeks": [{
            "week_ending": "2021-04-18",
            "hours": 4.0
        }, {
            "week_ending": "2021-02-28",
            "hours": 2.0
        }, {
            "week_ending": "2021-02-14",
            "hours": 5.0
        }, {
            "week_ending": "2020-11-22",
            "hours": 3.0
        }, {
            "week_ending": "2020-08-16",
            "hours": 2.0
        }]
    }, {
        "id": 14,
        "year": "2019-2020",
        "target": 18,
        "weeks": [{
            "week_ending": "2019-12-01",
            "hours": 2.0
        }, {
            "week_ending": "2019-10-27",
            "hours": 9.0
        }, {
            "week_ending": "2019-09-01",
            "hours": 2.5
        }]
    }, {
        "id": 12,
        "year": "2018-2019",
        "target": 20,
        "weeks": [{
            "week_ending": "2018-11-11",
            "hours": 4.0
        }, {
            "week_ending": "2018-08-26",
            "hours": 1.0
        }, {
            "week_ending": "2018-08-12",
            "hours": 12.0
        }]
    }]
}]

我要实现的目标:

[{
    "year": "2020-2021",
    "values": [{
        "name": "Test activity 51",
        "code": "D51",
        "description": "Description goes here.",
        "target": 65,
        "weeks": [{
            "week_ending": "2020-12-06",
            "hours": 4.0
        }, {
            "week_ending": "2020-12-06",
            "hours": 2.5
        }, {
            "week_ending": "2020-10-18",
            "hours": 2.0
        }, {
            "week_ending": "2020-07-19",
            "hours": 2.0
        }]
    }, {
        "name": "Test activity 59",
        "code": "D59",
        "description": null,
        "target": 15,
        "weeks": [{
            "week_ending": "2021-04-18",
            "hours": 4.0
        }, {
            "week_ending": "2021-02-28",
            "hours": 2.0
        }, {
            "week_ending": "2021-02-14",
            "hours": 5.0
        }, {
            "week_ending": "2020-11-22",
            "hours": 3.0
        }, {
            "week_ending": "2020-08-16",
            "hours": 2.0
        }]
    }, ]
}, {
    "year": "2019-2020",
    "values": [{
        "name": "Test activity 51",
        "code": "D51",
        "description": "Description goes here.",
        "target": 40,
        "weeks": [{
            "week_ending": "2020-01-05",
            "hours": 3.0
        }, {
            "week_ending": "2019-09-15",
            "hours": 5.5
        }, {
            "week_ending": "2019-07-14",
            "hours": 1.5
        }]
    }, {
        "name": "Test activity 63",
        "code": "D63",
        "description": null,
        "target": 15,
        "weeks": [{
            "week_ending": "2020-05-24",
            "hours": 2.0
        }, {
            "week_ending": "2020-03-22",
            "hours": 4.0
        }, {
            "week_ending": "2020-01-26",
            "hours": 5.0
        }, {
            "week_ending": "2020-01-19",
            "hours": 4.0
        }, {
            "week_ending": "2019-12-01",
            "hours": 4.5
        }, {
            "week_ending": "2019-08-25",
            "hours": 2.0
        }, {
            "week_ending": "2019-07-21",
            "hours": 3.0
        }]
    }, {
        "name": "Test activity 27",
        "code": "D27",
        "description": "Description goes here.",
        "target": 30,
        "weeks": [{
            "week_ending": "2020-04-05",
            "hours": 2.0
        }, {
            "week_ending": "2020-03-22",
            "hours": 6.0
        }, {
            "week_ending": "2020-01-12",
            "hours": 1.0
        }]
    }, {
        "name": "Test activity 59",
        "code": "D59",
        "description": null,
        "target": 18,
        "weeks": [{
            "week_ending": "2019-12-01",
            "hours": 2.0
        }, {
            "week_ending": "2019-10-27",
            "hours": 9.0
        }, {
            "week_ending": "2019-09-01",
            "hours": 2.5
        }]
    }, ]
}, {
    "year": "2018-2019",
    "values": [{
        "name": "Test activity 51",
        "code": "D51",
        "description": "Description goes here.",
        "target": 40,
        "weeks": [{
            "week_ending": "2018-09-30",
            "hours": 3.0
        }]
    }, {
        "name": "Test activity 63",
        "code": "D63",
        "description": null,
        "target": 30,
        "weeks": [{
            "week_ending": "2018-08-19",
            "hours": 3.5
        }, {
            "week_ending": "2019-02-10",
            "hours": 5.0
        }, {
            "week_ending": "2018-12-30",
            "hours": 3.0
        }, {
            "week_ending": "2018-10-21",
            "hours": 2.0
        }, {
            "week_ending": "2018-08-26",
            "hours": 4.0
        }]
    }, {
        "name": "Test activity 27",
        "code": "D27",
        "description": "Description goes here.",
        "target": 25,
        "weeks": [{
            "week_ending": "2018-11-18",
            "hours": 6.0
        }, {
            "week_ending": "2018-10-21",
            "hours": 2.0
        }, {
            "week_ending": "2018-10-07",
            "hours": 6.0
        }]
    }, {
        "name": "Test activity 59",
        "code": "D59",
        "description": null,
        "target": 20,
        "weeks": [{
            "week_ending": "2018-11-11",
            "hours": 4.0
        }, {
            "week_ending": "2018-08-26",
            "hours": 1.0
        }, {
            "week_ending": "2018-08-12",
            "hours": 12.0
        }]
    }]
}]        

最佳答案

对于 D3 nest,您的要求太复杂了。除此之外,d3.nest 无论如何都将被弃用...因此,这是一种纯 JavaScript 方法。

我们首先得到一组独特的年份:

const yearsList = [...new Set(data.map(d => d.years.map(e => e.year)).flat())];

然后,有了这个集合,我们循环遍历您的数据并创建一个新数组(这里称为 newData),在一个ad hoc 的解决方案中和冗长:

yearsList.forEach(d => {
  data.forEach(e => {

    const foundObject = e.years.find(f => f.year === d);

    if (foundObject) {

      const foundInNewData = newData.find(f => f.year === d);

      const values = {
        name: e.name,
        code: e.code,
        description: e.description,
        target: foundObject.target,
        weeks: foundObject.weeks
      };

      if (foundInNewData) {
        foundInNewData.values.push(values);
      } else {
        newData.push({
          year: d,
          values: [values]
        });
      };

    };

  });
});

这是演示:

const data = [{
    "id": 2,
    "name": "Test activity 51",
    "code": "D51",
    "description": "Description goes here.",
    "years": [{
        "id": 8,
        "year": "2020-2021",
        "target": 65,
        "weeks": [{
            "week_ending": "2020-12-06",
            "hours": 4.0
          },
          {
            "week_ending": "2020-12-06",
            "hours": 2.5
          },
          {
            "week_ending": "2020-10-18",
            "hours": 2.0
          },
          {
            "week_ending": "2020-07-19",
            "hours": 2.0
          }
        ]
      },
      {
        "id": 11,
        "year": "2019-2020",
        "target": 40,
        "weeks": [{
            "week_ending": "2020-01-05",
            "hours": 3.0
          },
          {
            "week_ending": "2019-09-15",
            "hours": 5.5
          },
          {
            "week_ending": "2019-07-14",
            "hours": 1.5
          }
        ]
      },
      {
        "id": 10,
        "year": "2018-2019",
        "target": 40,
        "weeks": [{
          "week_ending": "2018-09-30",
          "hours": 3.0
        }]
      }
    ]
  },
  {
    "id": 3,
    "name": "Test activity 63",
    "code": "D63",
    "description": null,
    "years": [{
        "id": 2,
        "year": "2019-2020",
        "target": 15,
        "weeks": [{
            "week_ending": "2020-05-24",
            "hours": 2.0
          },
          {
            "week_ending": "2020-03-22",
            "hours": 4.0
          },
          {
            "week_ending": "2020-01-26",
            "hours": 5.0
          },
          {
            "week_ending": "2020-01-19",
            "hours": 4.0
          },
          {
            "week_ending": "2019-12-01",
            "hours": 4.5
          },
          {
            "week_ending": "2019-08-25",
            "hours": 2.0
          },
          {
            "week_ending": "2019-07-21",
            "hours": 3.0
          }
        ]
      },
      {
        "id": 9,
        "year": "2018-2019",
        "target": 30,
        "weeks": [{
            "week_ending": "2018-08-19",
            "hours": 3.5
          },
          {
            "week_ending": "2019-02-10",
            "hours": 5.0
          },
          {
            "week_ending": "2018-12-30",
            "hours": 3.0
          },
          {
            "week_ending": "2018-10-21",
            "hours": 2.0
          },
          {
            "week_ending": "2018-08-26",
            "hours": 4.0
          }
        ]
      }
    ]
  },
  {
    "id": 1,
    "name": "Test activity 27",
    "code": "D27",
    "description": "Description goes here.",
    "years": [{
        "id": 4,
        "year": "2019-2020",
        "target": 30,
        "weeks": [{
            "week_ending": "2020-04-05",
            "hours": 2.0
          },
          {
            "week_ending": "2020-03-22",
            "hours": 6.0
          },
          {
            "week_ending": "2020-01-12",
            "hours": 1.0
          }
        ]
      },
      {
        "id": 1,
        "year": "2018-2019",
        "target": 25,
        "weeks": [{
            "week_ending": "2018-11-18",
            "hours": 6.0
          },
          {
            "week_ending": "2018-10-21",
            "hours": 2.0
          },
          {
            "week_ending": "2018-10-07",
            "hours": 6.0
          }
        ]
      }
    ]
  },
  {
    "id": 10,
    "name": "Test activity 59",
    "code": "D59",
    "description": null,
    "years": [{
        "id": 13,
        "year": "2020-2021",
        "target": 15,
        "weeks": [{
            "week_ending": "2021-04-18",
            "hours": 4.0
          },
          {
            "week_ending": "2021-02-28",
            "hours": 2.0
          },
          {
            "week_ending": "2021-02-14",
            "hours": 5.0
          },
          {
            "week_ending": "2020-11-22",
            "hours": 3.0
          },
          {
            "week_ending": "2020-08-16",
            "hours": 2.0
          }
        ]
      },
      {
        "id": 14,
        "year": "2019-2020",
        "target": 18,
        "weeks": [{
            "week_ending": "2019-12-01",
            "hours": 2.0
          },
          {
            "week_ending": "2019-10-27",
            "hours": 9.0
          },
          {
            "week_ending": "2019-09-01",
            "hours": 2.5
          }
        ]
      },
      {
        "id": 12,
        "year": "2018-2019",
        "target": 20,
        "weeks": [{
            "week_ending": "2018-11-11",
            "hours": 4.0
          },
          {
            "week_ending": "2018-08-26",
            "hours": 1.0
          },
          {
            "week_ending": "2018-08-12",
            "hours": 12.0
          }
        ]
      }
    ]
  }
];

const yearsList = [...new Set(data.map(d => d.years.map(e => e.year)).flat())];

const newData = [];

yearsList.forEach(d => {
  data.forEach(e => {
    const foundObject = e.years.find(f => f.year === d);
    if (foundObject) {
      const foundInNewData = newData.find(f => f.year === d);
      const values = {
        name: e.name,
        code: e.code,
        description: e.description,
        target: foundObject.target,
        weeks: foundObject.weeks
      };
      if (foundInNewData) {
        foundInNewData.values.push(values)
      } else {
        newData.push({
          year: d,
          values: [values]
        })
      }
    }
  })
});

console.log(newData)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

您会注意到,上面的代码不仅有一两个循环,还有三个 循环。如果您的数据数组太大,您还可以尝试仅使用两个嵌套循环的解决方案:

const newData = [];

data.forEach(d => {
  d.years.forEach(e => {
    const foundInNewData = newData.find(f => f.year === e.year);
    const values = {
      name: d.name,
      code: d.code,
      description: d.description,
      target: e.target,
      weeks: e.weeks
    };
    if (foundInNewData) {
      foundInNewData.values.push(values)
    } else {
      newData.push({
        year: e.year,
        values: [values]
      })
    }
  });
});

这是相应的演示:

const data = [{
    "id": 2,
    "name": "Test activity 51",
    "code": "D51",
    "description": "Description goes here.",
    "years": [{
        "id": 8,
        "year": "2020-2021",
        "target": 65,
        "weeks": [{
            "week_ending": "2020-12-06",
            "hours": 4.0
          },
          {
            "week_ending": "2020-12-06",
            "hours": 2.5
          },
          {
            "week_ending": "2020-10-18",
            "hours": 2.0
          },
          {
            "week_ending": "2020-07-19",
            "hours": 2.0
          }
        ]
      },
      {
        "id": 11,
        "year": "2019-2020",
        "target": 40,
        "weeks": [{
            "week_ending": "2020-01-05",
            "hours": 3.0
          },
          {
            "week_ending": "2019-09-15",
            "hours": 5.5
          },
          {
            "week_ending": "2019-07-14",
            "hours": 1.5
          }
        ]
      },
      {
        "id": 10,
        "year": "2018-2019",
        "target": 40,
        "weeks": [{
          "week_ending": "2018-09-30",
          "hours": 3.0
        }]
      }
    ]
  },
  {
    "id": 3,
    "name": "Test activity 63",
    "code": "D63",
    "description": null,
    "years": [{
        "id": 2,
        "year": "2019-2020",
        "target": 15,
        "weeks": [{
            "week_ending": "2020-05-24",
            "hours": 2.0
          },
          {
            "week_ending": "2020-03-22",
            "hours": 4.0
          },
          {
            "week_ending": "2020-01-26",
            "hours": 5.0
          },
          {
            "week_ending": "2020-01-19",
            "hours": 4.0
          },
          {
            "week_ending": "2019-12-01",
            "hours": 4.5
          },
          {
            "week_ending": "2019-08-25",
            "hours": 2.0
          },
          {
            "week_ending": "2019-07-21",
            "hours": 3.0
          }
        ]
      },
      {
        "id": 9,
        "year": "2018-2019",
        "target": 30,
        "weeks": [{
            "week_ending": "2018-08-19",
            "hours": 3.5
          },
          {
            "week_ending": "2019-02-10",
            "hours": 5.0
          },
          {
            "week_ending": "2018-12-30",
            "hours": 3.0
          },
          {
            "week_ending": "2018-10-21",
            "hours": 2.0
          },
          {
            "week_ending": "2018-08-26",
            "hours": 4.0
          }
        ]
      }
    ]
  },
  {
    "id": 1,
    "name": "Test activity 27",
    "code": "D27",
    "description": "Description goes here.",
    "years": [{
        "id": 4,
        "year": "2019-2020",
        "target": 30,
        "weeks": [{
            "week_ending": "2020-04-05",
            "hours": 2.0
          },
          {
            "week_ending": "2020-03-22",
            "hours": 6.0
          },
          {
            "week_ending": "2020-01-12",
            "hours": 1.0
          }
        ]
      },
      {
        "id": 1,
        "year": "2018-2019",
        "target": 25,
        "weeks": [{
            "week_ending": "2018-11-18",
            "hours": 6.0
          },
          {
            "week_ending": "2018-10-21",
            "hours": 2.0
          },
          {
            "week_ending": "2018-10-07",
            "hours": 6.0
          }
        ]
      }
    ]
  },
  {
    "id": 10,
    "name": "Test activity 59",
    "code": "D59",
    "description": null,
    "years": [{
        "id": 13,
        "year": "2020-2021",
        "target": 15,
        "weeks": [{
            "week_ending": "2021-04-18",
            "hours": 4.0
          },
          {
            "week_ending": "2021-02-28",
            "hours": 2.0
          },
          {
            "week_ending": "2021-02-14",
            "hours": 5.0
          },
          {
            "week_ending": "2020-11-22",
            "hours": 3.0
          },
          {
            "week_ending": "2020-08-16",
            "hours": 2.0
          }
        ]
      },
      {
        "id": 14,
        "year": "2019-2020",
        "target": 18,
        "weeks": [{
            "week_ending": "2019-12-01",
            "hours": 2.0
          },
          {
            "week_ending": "2019-10-27",
            "hours": 9.0
          },
          {
            "week_ending": "2019-09-01",
            "hours": 2.5
          }
        ]
      },
      {
        "id": 12,
        "year": "2018-2019",
        "target": 20,
        "weeks": [{
            "week_ending": "2018-11-11",
            "hours": 4.0
          },
          {
            "week_ending": "2018-08-26",
            "hours": 1.0
          },
          {
            "week_ending": "2018-08-12",
            "hours": 12.0
          }
        ]
      }
    ]
  }
];

const newData = [];

data.forEach(d => {
  d.years.forEach(e => {
    const foundInNewData = newData.find(f => f.year === e.year);
    const values = {
      name: d.name,
      code: d.code,
      description: d.description,
      target: e.target,
      weeks: e.weeks
    };
    if (foundInNewData) {
      foundInNewData.values.push(values)
    } else {
      newData.push({
        year: e.year,
        values: [values]
      })
    }
  });
});

console.log(newData)

关于javascript - 从 json 层次结构中较低的键嵌套或映射数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57949333/

相关文章:

javascript - 如何将变量放入 PhantomJS 生成的 HTML 标题中以进行 PDF 转换?

arrays - Angular 2 组件中的 Array.filter()

c++ - 为什么 char* p = "..."是对的,而 int* p = {1,2} 是错的?

javascript - IP 到国家/地区、城市、纬度、语言 javascript 服务

jquery - 使用 JQuery 从本地服务器解析 JSON 数据......但没有得到结果

javascript - 强制 qtip 仅在单击元素时出现?

javascript - Bootstrap Datetimepicker 在 Safari 中不工作

arrays - 如何将 NSManagedObject 值转换为具有键和值对的字典?

javascript - Zapier中的JavaScript使用分页来循环API调用

javascript - 在 2 个相似的表上使用 javascript 表搜索