【问题标题】:Organising List of Objects to Nested Arrays using Recursive String Path使用递归字符串路径将对象列表组织为嵌套数组
【发布时间】:2021-08-18 01:01:42
【问题描述】:

我有一个项目列表,这些项目可以有孩子,孩子也可以有孩子。我正在使用的 API 在单个对象数组中返回这些项目的列表,并提供一个 path 属性来使用该列表并按照您的选择组织它。每个孩子从0001 开始向path 添加一个额外递增的-000n。我不知道如何使用 path 值将对象列表组织成嵌套数组,其中每个项目都有自己的 children[] 数组。

我正在使用 Typescript/JS 和 Kotlin(Android 框架)。

一段时间以来,我一直在尝试解决这个问题,我希望社区能就这个问题提供一些意见。希望我已经解释得够清楚了,谢谢!

例子:

|--group (0001)
  |--item (0001-0001)
    |--item (0001-0001-0001)
      |--item (0001-0001-0001-0001)
      |--item (0001-0001-0001-0002)
  |--item (0001-0002)
    |--item (0001-0002-0001)
      |--item (0001-0002-0001-0001)
        |--item (0001-0002-0001-0001-0001)
      |--item (0001-0002-0001-0002)
  |--item (0001-0003)
|--group (0002)
  |--item (0002-0001)

有效载荷:

{
  "items": [
    {
      "name": "cameras",
      "type": "group",
      "path": "0001"
    },
    {
      "name": "camera-1",
      "type": "equipment",
      "path": "0001-0001"
    },
    {
      "name": "charger",
      "type": "power",
      "path": "0001-0001-0001"
    },
    {
      "name:": "cable",
      "type": "power",
      "path": "0001-0001-0001-0001"
    },
    {
      "name": "adapter",
      "type": "power",
      "path": "0001-0001-0001-0002"
    },
    {
      "name": "camera-2",
      "type": "equipment",
      "path": "0001-0002"
    },
    // etc
    {
      "name": "lights",
      "type": "group",
      "path": "0002"
    }
    // etc
  ]
}

首选结果:

{
  "items": [
    {
      "name": "cameras",
      "type": "group",
      "path": "0001",
      "children": [
        {
          "name": "camera-1",
          "type": "equipment",
          "path": "0001-0001",
          "children": [
            {
              "name": "charger",
              "type": "power",
              "path": "0001-0001-0001",
              "children": [
                {
                  "name:": "cable",
                  "type": "power",
                  "path": "0001-0001-0001-0001"
                },
                {
                  "name": "adapter",
                  "type": "power",
                  "path": "0001-0001-0001-0002"
                }
              ]
            }
          ]
        },
        {
            "name": "camera-2",
            "type": "equipment",
            "path": "0001-0002",
            // children as above
        }
      ]
    },
    {
        "name": "lights",
        "type": "group",
        "path": "0002",
        // children as above
    }
  ]
}

【问题讨论】:

    标签: android json typescript kotlin recursion


    【解决方案1】:

    您可以在构建项目树时使用地图按路径存储项目。这是一个例子:

    data class Item(
        val name: String,
        val type: String,
        val path: String,
        val children: MutableList<Item> = mutableListOf(),
    )
    
    val itemsList = <flat list of items, parsed from json>
    val pathMap = mutableMapOf<String, Item>()
    val itemsTree = mutableListOf<Item>()
    for (item in itemsList) {
        pathMap[item.path] = item
        if ('-' in item.path) {
            val parentPath = item.path.substringBeforeLast('-')
            val parent = pathMap[parentPath]
            if (parent != null) {
                parent.children += item
            }
        } else {
            itemsTree += item
        }
    }
    

    这里itemsList 是项目的原始列表,在一个平面层次结构中,itemsTree 是一个顶级项目列表,每个项目都有一个包含子项目的children 属性。但是,这确实要求所有“父母”出现在itemsList 中的任何孩子之前,但可以轻松修改以说明情况并非如此。

    我不确定你想要 Kotlin 还是 TypeScript,但两者的概念很容易互换,你只需要一个类似地图的数据结构。

    【讨论】:

    • 这很好,当我记录itemsTree 的结果时似乎可以正常工作,谢谢!我正在努力理解地图和项目之间的关系。地图中的孩子如何添加到树中?对不起,如果我是愚蠢的。
    • 映射允许您将值与键相关联。这里的关键是路径。由于父路径包含在子路径中,我们可以从地图中获取父项,并添加一个新子项。如果项目是顶级的(没有-),则将其添加到树的根。在这段代码中永远不会创建项目,只会创建新的引用。
    • 啊,我明白你的意思了。很好的解决方案,非常感谢您花时间解释。
    猜你喜欢
    • 1970-01-01
    • 2019-02-08
    • 1970-01-01
    • 2021-07-12
    • 1970-01-01
    • 2021-08-21
    • 1970-01-01
    • 2012-03-26
    相关资源
    最近更新 更多