【问题标题】:Converting array of object to hierarchical data structure将对象数组转换为分层数据结构
【发布时间】:2021-07-15 20:07:14
【问题描述】:

我有一个原始数组,我想将它绘制在需要分层数据结构的 Sunburst 地图中。

[
{id: "Asia,India,NewDelhi", value: 41},
{id: "Europe,Germany,Berlin", value: 24},
{id: "Europe,England,London", value: 3},
{id: "NorthAmerica,USA,NewYork", value: 4},
{id: "NorthAmerica,USA,Boston", value: 3},
{id: "NorthAmerica,USA,chicago", value: 3},
{id: "Austrailia,Sydney", value: 4},
{id: "Asia,China,Beijing", value: 2},
]

想要的结果

[
  {
   id: Asia,
   children:[{
     id: India,
     children:[{
       id: Delhi,
       value: 41,
        }]
     },
     {
      id:China,
      children:[{
        id: Beijing
        value: 2,
        }]
     }]
  },
  {
    id: Europe,
    children: [{
       id: Germany,
       children: [{
          id: Berlin,
          value: 24,
       }]
    },
    {
       id: England,
       children: [{
         id: London,
         value: 3,
       }]
    }]
  },
  {
   id: NorthAmerica,
   children:[{
      id: USA,
      children:[{
        id: NewYork,
        value: 4, 
      },
      {
        id: Boston,
        value: 3,
      },
      {
        id: Chicago,
        value: 3,
      }]
   }]
  },
  {
   id: Austrailia
   children: [{
     id:Sydney,
     value: 4,
     }]
  },
]

谁能帮我解决这个问题,我尝试使用 reduce 方法,但我无法得到想要的结果。

PS:如果有人能提出一个可以处理 n 个用逗号分隔的 id 的答案,那将非常有用。例如:这里我们有 3 个用逗号分隔的 id 层次结构,如果有 4 或 5 个深度数据会发生什么。

【问题讨论】:

    标签: javascript arrays reactjs d3.js nivo-react


    【解决方案1】:

    一个简单的递归解决方案:

    const data = [
      {id: "Asia,India,NewDelhi", value: 41},
      {id: "Europe,Germany,Berlin", value: 24},
      {id: "Europe,England,London", value: 3},
      {id: "NorthAmerica,USA,NewYork", value: 4},
      {id: "NorthAmerica,USA,Boston", value: 3},
      {id: "NorthAmerica,USA,Chicago", value: 3},
      {id: "Austrailia,Sydney", value: 4},
      {id: "Asia,China,Beijing", value: 2},
    ];
    
    const addChild = (ids, value, arr) => {
      const id = ids.shift();
      let index = arr.findIndex(item => item.id === id);
      if (index < 0) {
        arr.push({id, children: []});
        index = arr.length - 1;
      }
      if (ids.length > 0) {
        const children = arr[index].children;
        addChild(ids, value, children);
      }
      else
        arr[index].value = value;
    }
    
    const treeData = data.reduce((tree, item) => {
      const ids = item.id.split(',');
      addChild(ids, item.value, tree);
      return tree;
    }, []);
    
    console.log(treeData);

    【讨论】:

      【解决方案2】:

      从您的输入构建对象 的层次结构相当简单,您甚至不需要做任何递归循环+reduce 就可以做到。这将适用于逗号分隔列表中的任意数量的级别。

      const input = [
      {id: "Asia,India,NewDelhi", value: 41},
      {id: "Europe,Germany,Berlin", value: 24},
      {id: "Europe,England,London", value: 3},
      {id: "NorthAmerica,USA,NewYork", value: 4},
      {id: "NorthAmerica,USA,Boston", value: 3},
      {id: "NorthAmerica,USA,chicago", value: 3},
      {id: "Austrailia,Sydney", value: 4},
      {id: "Asia,China,Beijing", value: 2}
      ]
      const result = input.map(o => ({ids:o.id.split(","), value:o.value})).reduce( (acc,obj) => {
         let curr = acc;
         let id;
         while( (id = obj.ids.shift()) != null ){
           if(!curr[id])
              curr[id] = {};
              
           curr = curr[id];
         }
         curr.value = obj.value
         return acc;
      },{});
      console.log(result);
      .as-console-wrapper { max-height: 100% !important; top: 0; }

      然后将其转换为您想要的格式确实需要一些递归:

      const input = [
      {id: "Asia,India,NewDelhi", value: 41},
      {id: "Europe,Germany,Berlin", value: 24},
      {id: "Europe,England,London", value: 3},
      {id: "NorthAmerica,USA,NewYork", value: 4},
      {id: "NorthAmerica,USA,Boston", value: 3},
      {id: "NorthAmerica,USA,chicago", value: 3},
      {id: "Austrailia,Sydney", value: 4},
      {id: "Asia,China,Beijing", value: 2}
      ]
      const result = input.map(o => ({ids:o.id.split(","), value:o.value})).reduce( (acc,obj) => {
         let curr = acc;
         let id;
         while( (id = obj.ids.shift()) != null ){
           if(!curr[id])
              curr[id] = {};
              
           curr = curr[id];
         }
         curr.value = obj.value
         return acc;
      },{});
      
      function buildHierarchy(input){
        return Object.entries(input).map( ([id,children]) => {
          if(children.value){
            return {id,value:children.value}
          }
          return {id, children: buildHierarchy(children)}
        })
      }
      
      console.log(buildHierarchy(result));
      .as-console-wrapper { max-height: 100% !important; top: 0; }

      【讨论】:

        猜你喜欢
        • 2021-10-03
        • 1970-01-01
        • 1970-01-01
        • 2018-03-10
        • 2022-11-24
        • 2021-11-12
        • 1970-01-01
        相关资源
        最近更新 更多