首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >从平面数组数据结构创建嵌套数组

从平面数组数据结构创建嵌套数组
EN

Stack Overflow用户
提问于 2020-06-02 03:20:58
回答 5查看 622关注 0票数 0

我需要创建一个嵌套数组,使用路径作为子对象的引用。例如: 4.1是4的孩子,4.1.1是4.1的孩子,4.2是4的孩子.我有一个平面数组,里面有所有的数据和路径。创建嵌套数组的最佳方法是如何根据其路径将子数组嵌套到其父数组。

输入:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const list = [
  {
    location: 1,
    path: '4'
  },
  {
    location: 2,
    path: '4.1'
  },  
  {
    location: 3,
    path: '4.1.1'
  },  
  {
    location: 4,
    path: '4.1.2'
  },  
  {
    location: 5,
    path: '4.2'
  },  
  {
    location: 6,
    path: '4.2.1'
  },
  {
    location: 7,
    path: '4.3'
  },
  {
    location: 8,
    path: '4.3.1'
  }
];

输出:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const  list = [
  {
    location: 1,
    path: '4',
        children: [
            {
            location: 2,
            path: '4.1',
            children: [
                {
                    location: 3,
                    path: '4.1.1'
                },  
                {
                    location: 4,
                    path: '4.1.2'
                },  
            ]
        },  
            {
                location: 5,
                path: '4.2',
                children: [
                    {
                        location: 6,
                        path: '4.2.1'
                    },
                ]
            },  
            {
                location: 7,
                path: '4.3',
                children: [
                    {
                        location: 8,
                        path: '4.3.1'
                    }
                ]
            },
        ]
  },
];

最好的方法是递归。对这个算法有什么建议吗?

EN

回答 5

Stack Overflow用户

发布于 2020-06-02 04:35:29

您可以首先按路径对对象数组进行排序,以便父对象在排序后的数组中始终位于其子对象之前。例如:“4”将在“4.1”之前

现在,您可以创建一个对象,其中的关键字是路径。让我们假设'4‘已经插入到我们的对象中。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
obj = {
  '4': {
    "location": 1,
    "path": "4",    
  }
}

当我们处理'4.1‘时,我们首先检查'4’是否存在于我们的对象中。如果是,我们现在进入它的子对象(如果键‘check’不存在,我们创建一个新的空对象)并检查'4.1‘是否存在。如果不是,我们插入'4.1‘

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
obj = {
  '4': {
    "location": 1,
    "path": "4",
    "children": {
      "4.1": {
        "location": 2,
        "path": "4.1"
      }
    }
  }
}

我们对列表中的每个元素重复这个过程。最后,我们只需要将这个对象递归地转换为一个对象数组。

最终代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
list.sort(function(a, b) {
  return a.path - b.path;
})

let obj = {}

list.forEach(x => {
  let cur = obj;
  for (let i = 0; i < x.path.length; i += 2) {
    console.log(x.path.substring(0, i + 1))
    if (x.path.substring(0, i + 1) in cur) {
      cur = cur[x.path.substring(0, i + 1)]
      if (!('children' in cur)) {
        cur['children'] = {}
      }
      cur = cur['children']
    } else {
      break;
    }
  }
  cur[x.path] = x;
})

function recurse (obj) {
  let res = [];
  Object.keys(obj).forEach((key) => {
    if (obj[key]['children'] !== null && typeof obj[key]['children'] === 'object') {
      obj[key]['children'] = recurse(obj[key]['children'])
    }
    res.push(obj[key])
  })
  return res;
}

console.log(recurse(obj));
票数 1
EN

Stack Overflow用户

发布于 2020-06-02 13:40:58

要做到这一点,一种方法是使用将路径映射到对象的中间索引,然后通过在索引中查找每个节点及其父节点将列表折叠到一个结构中。如果没有父对象,则将其添加到根对象中。最后,我们返回根对象的子对象。下面是一些代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const restructure = (list) => {
  const index = list .reduce(
    (a, {path, ...rest}) => ({...a, [path]: {path, ...rest}}), 
    {}
  )
  
  return list .reduce((root, {path}) => {
    const node = index [path]
    const parent = index [path .split('.') .slice(0, -1) .join('.')] || root
    parent.children = [...(parent.children || []), node]
    return root
  }, {children: []}) .children
}

const list = [{location: 1, path: '4'}, {location: 2, path: '4.1' }, {location: 3, path: '4.1.1'}, {location: 4, path: '4.1.2'}, {location: 5, path: '4.2'}, {location: 6, path: '4.2.1'}, {location: 7, path: '4.3'}, {location: 8, path: '4.3.1'}]

console.log (restructure (list))
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
.as-console-wrapper {min-height: 100% !important; top: 0}

使用索引意味着我们不需要对任何东西进行排序;输入可以是任何顺序。

例如,查找父对象需要用"4.3"替换"4.3.1"并在索引中查找它。当我们尝试"4"时,它会查找空字符串,但找不到它,并使用根节点。

如果您更喜欢正则表达式,您可以使用下面这行稍微短一点的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    const parent = index [path.replace (/(^|\.)[^.]+$/, '')] || root

但是,对于类似的问题,您可能还想在recent answer中查看一种更优雅的技术。我在这里的答案是,完成了这项工作(有一点丑陋的变化),但这个答案将教你很多关于有效软件开发的知识。

票数 1
EN

Stack Overflow用户

发布于 2020-06-02 16:34:08

我很好奇Scott的链接答案是否能够在不修改的情况下解决这个问题。确实是这样!

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import { tree } from './Tree'
import { bind } from './Func'

const parent = (path = "") =>
  bind
    ( (pos = path.lastIndexOf(".")) =>
        pos === -1
          ? null
          : path.substr(0, pos)
    )

const myTree =
  tree                          // <- make tree
    ( list                      // <- array of nodes
    , node => parent(node.path) // <- foreign key
    , (node, children) =>       // <- node reconstructor
        ({ ...node, children: children(node.path) }) // <- primary key
    )

console.log(JSON.stringify(myTree, null, 2))
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[
  {
    "location": 1,
    "path": "4",
    "children": [
      {
        "location": 2,
        "path": "4.1",
        "children": [
          {
            "location": 3,
            "path": "4.1.1",
            "children": []
          },
          {
            "location": 4,
            "path": "4.1.2",
            "children": []
          }
        ]
      },
      {
        "location": 5,
        "path": "4.2",
        "children": [
          {
            "location": 6,
            "path": "4.2.1",
            "children": []
          }
        ]
      },
      {
        "location": 7,
        "path": "4.3",
        "children": [
          {
            "location": 8,
            "path": "4.3.1",
            "children": []
          }
        ]
      }
    ]
  }
]

Tree模块在this post中共享,下面来看一下提供bindFunc模块-

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// Func.js
const identity = x => x

const bind = (f, ...args) =>
  f(...args)

const raise = (msg = "") => // functional throw
  { throw Error(msg) }

// ...

export { identity, bind, raise, ... }

展开下面的代码片段,在浏览器中验证结果-

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// Func.js
const bind = (f, ...args) =>
  f(...args)
  
// Index.js
const empty = _ =>
  new Map

const update = (r, k, t) =>
  r.set(k, t(r.get(k)))

const append = (r, k, v) =>
  update(r, k, (all = []) => [...all, v])

const index = (all = [], indexer) =>
  all.reduce
      ( (r, v) => append(r, indexer(v), v)
      , empty()
      )
      
// Tree.js
// import { index } from './Index'
function tree (all, indexer, maker, root = null)
{ const cache =
    index(all, indexer)

  const many = (all = []) =>
    all.map(x => one(x))
    
  const one = (single) =>
    maker(single, next => many(cache.get(next)))

  return many(cache.get(root))
}

// Main.js
// import { tree } from './Tree'
// import { bind } from './Func'

const parent = (path = "") =>
  bind
    ( (pos = path.lastIndexOf(".")) =>
        pos === -1
          ? null
          : path.substr(0, pos)
    )

const list =
  [{location:1,path:'4'},{location:2,path:'4.1'},{location:3,path:'4.1.1'},{location:4,path:'4.1.2'},{location:5,path:'4.2'},{location:6,path:'4.2.1'},{location:7,path:'4.3'},{location:8,path:'4.3.1'}]

const myTree =
  tree
    ( list                      // <- array of nodes
    , node => parent(node.path) // <- foreign key
    , (node, children) =>       // <- node reconstructor
        ({ ...node, children: children(node.path) }) // <- primary key
    )

console.log(JSON.stringify(myTree, null, 2))

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62144258

复制
相关文章
python创建新数组_python怎么创建数组
2.间接定义matrix=[0 for i in range(4)]  print(matrix)
全栈程序员站长
2022/06/26
4.6K0
LeetCode 565. 数组嵌套
索引从0开始长度为N的数组A,包含0到N - 1的所有整数。 找到最大的集合S并返回其大小,其中 S[i] = {A[i], A[A[i]], A[A[A[i]]], ... }且遵守以下的规则。
Michael阿明
2020/07/13
6570
嵌套数组的合并,扁平化数组
对于 [ [], [], [], ...] 数组里嵌套数组,有个需求:将里面的数组元素都放到外层数组,变成 , , , ...
Krry
2018/10/12
2.2K0
嵌套数组的合并,扁平化数组
numpy创建数组
NumPy系统是Python的一种开源的数值计算扩展。这种工具可用来存储和处理大型矩阵,比Python自身的嵌套列表(nested list structure)结构要高效的多(该结构也可以用来表示矩阵(matrix))。
全栈程序员站长
2022/06/26
1.6K0
numpy创建数组
动态创建数组[通俗易懂]
使用运算符new也可以创建数组类型的对象,这时需要给出数组的结构说明。用new运算符动态创建一维数组的语法形式为: new 类型名【数组长度】; 其中数组长度指出了数组元素的个数,它可以是任何能够得到正整数值的表达式。 细节: 用new动态创建一维数组时,在方括号后仍然可以加小括号“()”,但小括号内不能带任何参数。是否加“()”的区别在于,不加“()”,则对数组每个元素的初始化,与执行“new T”时所进行初始化的方式相同;加“()”,则与执行“new T()”所进行初始化的方式相同。例如,如果这样动态生成一个整型数组: int *p=new int[10] (); 则可以方便地为动态创建的数组用0值初始化。 如果是用new建立的数组,用delete删除时所在指针名前面要加上“【】”,格式如下: delete[] 指针名;
全栈程序员站长
2022/08/15
3K0
JS 递归 数组嵌套回显
第一种: // 查询部门信息 seeBranch(data,id){ function find(data, fn, result) { data.forEach(item => { if(item.id===id){ result.push(item) }else if (item.children.length>0) { find(item.children, fn, result) } else { if (f
我不是费圆
2022/05/09
4K0
数据结构-数组
---- 数据结构-数组 数组 数据结构中最基本的一个结构就是线性结构,而线性结构又分为连续存储结构和离散存储结构。所谓的连续存储结构其实就是数组。 优点:查询较快如果知道坐标可以快速去地存取 缺点:删除慢,大小固定 二次封装数组的增删改查 基类的定义 定义一个工具类名称-Array 接受的参数包括基本类型和自定义类型(用泛型来接受,基本类型用包装类) 自定义属性两个:size用来表示数组的大小,data用来表示一个准确的集合 概念区分:size表示数组的大小,capacity表示数组容量的大小 构造函
杨小杰
2019/06/03
1.1K0
数据结构-数组
工作了一段时间后,发现基础实在是太重要了,老话说: 万丈高楼平地起。地基不牢,肯定跑不快,天花板也愈发明显。
用户1081422
2020/04/08
4170
数据结构-数组
数组(Array)是一种线性表数据结构。它用一组连续的内存空间,来存储一组具有相同类型的数据。
acc8226
2022/05/17
3190
java对象数组 创建对象数组,初始化对象数组
对象数组的概念: 如果一个数组中的元素是对象类型,则称该数组为对象数组。 当需要一个类的多个对象时,应该用该类的对象数组来表示,通过改变下标值就可以访问到不同的对象。 对象数组的定义和使用: 对象数组的定义与一般数组的定义类似,但是需要为每一个元素实例化。 对象数组的声明形式是: 类名 对象数组名 [ ]; 为对象数组分配内存空间: 对象数组名=new 类名[数组长度];//注意 :此处不是构造方法了 可以将对象数组的声明和创建用一条语句来完成。例如:定义一个学生类对象数组,可以用下面的语句定义:Student stu[ ]=new Student[30]; stu [ ]是对象数组名,它所表示的数组一共有30个元素,每一个元素都是Student类的对象名,还没有实例化,所以还必须为每一个元素实例化。比如如下的过程: for(int i=0;i<stu.length;i++) stu[i]=new Student(); 实例化以后就可以使用每一个元素对象。 设计一个雇员类,并创建雇员类的对象数组,输出每个雇员的信息
用户7886150
2021/02/01
3.9K0
python里数组如何定义_Python创建数组
arr = [i for i in range(10), 1,[]] #注意, i for in xx 这个必须放在第一个位置,否则要先定义i,
全栈程序员站长
2022/09/22
4K0
vue elementUI 表单校验(数组多层嵌套)
在使用vue element-ui form表单渲染的时候,会遇到这样的数据结构:
蓓蕾心晴
2019/06/05
5.2K0
String数组的创建
因为java是强类型语言,声明变量的时候要指定变量的类型,使用前者更能清楚表达数组类型,而使用后者,光看类型是不知道是数组还是int的。
全栈程序员站长
2022/06/26
1.7K0
用new创建数组
由于new创建的对象是在运行时确立的,所以有着具体情况具体分析的优点,那么什么叫做具体情况具体分析呢?我觉得c++ primer plus的一个例子十分贴切——比如你在度假,已经做好每天的参观计划,可突然有一天天气不好或你心情不好,此时你就不想参观了,如果此时是在编译状态,系统是不允许的,你必须按照计划去参观,但运行时状态,系统是允许的,此时你就可以呆在酒店尽情的玩耍了。用new创建数组也有此优点,即数组长度可以根据情况而定。
全栈程序员站长
2022/08/28
6230
用new创建数组
numpy入门-数组创建
Numpy 基础知识 Numpy的主要对象是同质的多维数组。Numpy中的元素放在[]中,其中的元素通常都是数字,并且是同样的类型,由一个正整数元组进行索引。 每个元素在内存中占有同样大小的空间。在Numpy中,维度被称为轴。例如对于[1, 2, 1]有一个轴,并且长度为3。而[[ 1., 0., 0.], [ 0., 1., 2.]]则有两个轴,第一个轴的长度为2,第二个轴的长度为3。 Numpy数组类的名字叫做ndarray,经常简称为array。要注意将numpy.array与标准Python库中的a
皮大大
2021/03/02
1.1K0
MONGODB 嵌套数组更新 与 设计
(注:最近我发现MONGODB 的文字,大家好像不大感兴趣,不知道是大家的公司不使用MONGBDB 还是由于MONGODB 太稳定,所以就忽略了,其实MONGODB 可以聊的话题和使用的范围很大,有的公司可能主力数据库就是MONGODB 所以MONGODB 确实不是可有可无的)
AustinDatabases
2019/09/05
3.3K0
MONGODB  嵌套数组更新 与   设计
PL/SQL 联合数组与嵌套表
      通常情况下,在PL/SQL中,处理单行单列的数据可以使用标量变量,而处理单行多列的数据则使用PL/SQL记录是不错的选择。单列多行数据 则由联合数组或嵌套表来完成,其特点是类似于单列数据库表。在Oracle 9i 之前称为PL/SQL索引表,9i 之后称之为联合数组。嵌套表也是集合 类型中的一种,下面分别介绍这两种集合数据类型的使用方法。
Leshami
2018/08/14
1.3K0
数据结构之数组
1、数据结构研究的是数据如何在计算机中进行组织和存储,使得我们可以高效的获取数据或者修改数据。
别先生
2020/03/19
6180
数据结构--树状数组
树状数组的核心函数lowbit(int m):作用是求出 m 的二进制表示的末尾1的位置,对于要查询 m 的前缀和,m = m - lowbit(m) 代表不断对二进制末尾1进行-1操作,不断执行直到 m == 0 结束,就能得到前缀和由哪几个Cm构成
Michael阿明
2020/07/13
1.9K0
数据结构--树状数组
数据结构(5):数组
数组是由 n(n≥1)个相同类型的数据元素构成的有限序列,每个数据元素称为一个数组元素,每个元素在 n 个线性关系中的序号称为该元素的下标,下标的取值范围称为数组的维界。
不可言诉的深渊
2021/04/16
9690

相似问题

从平面数组创建嵌套对象

23

从平面数组创建嵌套数组- JavaScript

27

使用子数组从平面数组创建嵌套数组

13

从平面文件创建嵌套数组

25

从PHP平面数组创建嵌套UL

11
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文