【问题标题】:Nesting or mapping data from key lower in json hierarchy从 json 层次结构中的较低键嵌套或映射数据
【发布时间】:2020-01-16 20:20:06
【问题描述】:

我需要重新组织我的 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
        }]
    }]
}]        

【问题讨论】:

    标签: javascript arrays json d3.js


    【解决方案1】:

    你的问题对于 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)

    【讨论】:

    • 太棒了,谢谢。为什么故意冗长?也许是为了更容易理解?
    • @tgerard 是的,你明白了。有时 S.O.用户写出精彩的答案,简洁明了,看起来像是一场代码高尔夫比赛,但很难理解。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多