【问题标题】:Create a tree-like json object from an array of objects从对象数组创建树状 json 对象
【发布时间】:2018-04-24 09:38:20
【问题描述】:

我是 javascript 对象和树创建的初学者,所以请多多包涵。 我有一个这样的对象数组

[
    {
        "l1": 1,
        "l2": 2,
        "l3": 3,
        "l4": 4,
        "l5": 5,
        "l6": null
    },
    {
        "l1": 1,
        "l2": 2,
        "l3": 3,
        "l4": 4,
        "l5": 6,
        "l6": null
    },
    {
        "l1": 1,
        "l2": 2,
        "l3": 7,
        "l4": 8,
        "l5": 9,
        "l6": null
    },
    {
        "l1": 1,
        "l2": 2,
        "l3": 7,
        "l4": 8,
        "l5": 10,
        "l6": null
    },
    {
        "l1": 1,
        "l2": 2,
        "l3": 3,
        "l4": 11,
        "l5": 12,
        "l6": null
    },
    {
        "l1": 1,
        "l2": 2,
        "l3": 3,
        "l4": 11,
        "l5": 13,
        "l6": null
    }
]

我已将此数据存储在 json 文件中,并且我想使用此对象数组创建一个类似树结构的对象。像这样。

{
  "1": [
    {
      "2": [
        {
          "3": [
            {
              "4": [
                {
                  "5": [
                    null
                  ]
                },
                {
                  "6": [
                    null
                  ]
                }
              ]
            },
            {
              "11": [
                {
                  "12": [
                    null
                  ]
                },
                {
                  "13": [
                    null
                  ]
                }
              ]
            }
          ]
        },
        {
          "7": [
            {
              "8": [
                {
                  "9": [
                    null
                  ]
                },
                {
                  "10": [
                    null
                  ]
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

我正在尝试自己做这件事,但我一开始就失败了。

这是我的尝试

var fs = require('fs');
var file = 'levels.json';
var content = fs.readFileSync(file, { encoding: 'binary' });
var obj = {}
JSON.parse(content).forEach((curr, i, arr)=>{
    if(curr.l1){
        obj[curr.l1] = []
    }
    if(curr.l2){
        var l2obj = {}
        l2obj[curr.l2] = []
        obj[curr.l1].push(l2obj)
        // obj[curr.l1].push({curr.l2:[]})
    }
})

fs.writeFileSync('theObject.json', JSON.stringify(obj), 'utf8');

我发现的问题是l2obj[curr.l2] = [] 行覆盖了先前的数组,我无法正确嵌套它们。obj[curr.l1] = [] 行也存在同样的问题。我也尝试了注释行,但它抛出了语法错误。我觉得它非常基本但也非常令人困惑,我如何从动态值创建对象并将它们推送到数组而不覆盖前一个数组。任何建议、提示。
第二行问题,这是表示此类数据的最佳方式吗?我想使用树形结构,因为它看起来是一种准确且最短的数据结构形式。json 数据有近 20k 个对象和级别信息。非常感谢您的建议。

【问题讨论】:

  • 您能解释一下转换背后的预期逻辑吗?
  • 我有一个大列表(几乎 20k 行)类别名称及其子类别名称嵌套多达 6 个级别。我假设树结构将是找到直接兄弟姐妹和父母的最佳(最短)数据结构。

标签: javascript arrays object tree


【解决方案1】:

您可以先构建一个不带数组的不同嵌套结构,然后使用其他递归函数遍历该数据并将其更改为所需的输出。

const data =[{"l1":1,"l2":2,"l3":3,"l4":4,"l5":5,"l6":null},{"l1":1,"l2":2,"l3":3,"l4":4,"l5":6,"l6":null},{"l1":1,"l2":2,"l3":7,"l4":8,"l5":9,"l6":null},{"l1":1,"l2":2,"l3":7,"l4":8,"l5":10,"l6":null},{"l1":1,"l2":2,"l3":3,"l4":11,"l5":12,"l6":null},{"l1":1,"l2":2,"l3":3,"l4":11,"l5":13,"l6":null}]
const result = {}

data.forEach(o => {
  Object.keys(o).reduce((r, e, i, arr) => {
    const key = o[e];
    if (o[e] == null) return r;
    if (o[arr[i + 1]] == null) r[key] = null
    else if (!r[key]) r[key] = {}
    return r[key]
  }, result)
})

function build(input) {
  for (let key in input) {
    if (input[key] && Object.keys(input[key]).length) build(input[key]);
    input[key] = [input[key]]
  }
}

build(result)

console.log(result)

更新:您也可以使用这样的对象获得嵌套结构。

const data =[{"l1":1,"l2":2,"l3":3,"l4":4,"l5":5,"l6":null},{"l1":1,"l2":2,"l3":3,"l4":4,"l5":6,"l6":null},{"l1":1,"l2":2,"l3":7,"l4":8,"l5":9,"l6":null},{"l1":1,"l2":2,"l3":7,"l4":8,"l5":10,"l6":null},{"l1":1,"l2":2,"l3":3,"l4":11,"l5":12,"l6":null},{"l1":1,"l2":2,"l3":3,"l4":11,"l5":13,"l6":null}]
const result = {}

data.forEach(o => {
  Object.keys(o).reduce((r, e) => {
    if (o[e] == null) return r;
    return r[o[e]] = (r[o[e]] || {})
  }, result)
})

console.log(result)

【讨论】:

    【解决方案2】:

    我想通了,我必须改变结果的格式,而不是我使用对象格式本身的数组。我意识到数组数据结构违背了我的目的。 所以我真正想要的结果是

    {
      "1": {
        "2": {
          "3": {
            "4": {
              "5": {},
              "6": {}
            },
            "11": {
              "12": {},
              "13": {}
            }
          },
          "7": {
            "8": {
              "9": {},
              "10": {}
            }
          }
        }
      }
    }
    

    解决方案看起来有点奇怪,但很容易理解,我运行了 6 遍来创建嵌套对象。

    var data = JSON.parse(content)
    data.forEach((curr, i, arr)=>{
        if(curr.l1){
            obj[curr.l1] = {}
        }
    })
    data.forEach((curr, i, arr)=>{
        if(curr.l2 ){            
            obj[curr.l1][curr.l2] = {}
        }
    })
    data.forEach((curr, i, arr)=>{
        if(curr.l3 ){            
            obj[curr.l1][curr.l2][curr.l3] = {}
        }
    })
    data.forEach((curr, i, arr)=>{
        if(curr.l4 ){            
            obj[curr.l1][curr.l2][curr.l3][curr.l4] = {}
        }
    })
    data.forEach((curr, i, arr)=>{
        if(curr.l5 ){            
            obj[curr.l1][curr.l2][curr.l3][curr.l4][curr.l5] = {}
        }
    })
    data.forEach((curr, i, arr)=>{
        if(curr.l6 ){            
            obj[curr.l1][curr.l2][curr.l3][curr.l4][curr.l5][curr.l6] = {}
        }
    })
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-08
      • 2012-12-14
      • 1970-01-01
      • 2014-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-04
      相关资源
      最近更新 更多