首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

从数组生成树,并将父字段的表示形式更改为object而不是ID

,可以使用递归算法来实现。

首先,我们需要定义一个数据结构来表示树节点。每个节点应该包含一个唯一的标识符,一个表示节点值的字段,以及一个指向父节点的引用或者对象。

代码语言:txt
复制
class TreeNode {
  constructor(id, value, parent) {
    this.id = id;
    this.value = value;
    this.parent = parent;
    this.children = [];
  }
}

然后,我们可以编写一个函数来生成树。该函数接收一个包含所有节点的数组和一个表示父字段的字符串参数。

代码语言:txt
复制
function generateTree(nodes, parentField) {
  // 创建一个空的节点映射表,用于根据id查找节点
  const nodeMap = {};

  // 构建节点映射表
  for (const node of nodes) {
    nodeMap[node.id] = new TreeNode(node.id, node.value, null);
  }

  // 构建树结构
  for (const node of nodes) {
    const parentNode = nodeMap[node[parentField]];
    const currentNode = nodeMap[node.id];

    // 将当前节点添加到父节点的子节点列表中
    if (parentNode) {
      parentNode.children.push(currentNode);
      currentNode.parent = parentNode;
    }
  }

  // 返回根节点
  return Object.values(nodeMap).find(node => !node.parent);
}

使用示例:

代码语言:txt
复制
const nodes = [
  { id: 1, value: 'A', parent: null },
  { id: 2, value: 'B', parent: 1 },
  { id: 3, value: 'C', parent: 1 },
  { id: 4, value: 'D', parent: 2 },
  { id: 5, value: 'E', parent: 2 },
  { id: 6, value: 'F', parent: 3 },
];

const tree = generateTree(nodes, 'parent');
console.log(tree);

输出结果:

代码语言:txt
复制
TreeNode {
  id: 1,
  value: 'A',
  parent: null,
  children: [
    TreeNode { id: 2, value: 'B', parent: [Circular], children: [Array] },
    TreeNode { id: 3, value: 'C', parent: [Circular], children: [Array] }
  ]
}

对于父字段的表示形式更改为对象而不是ID,可以修改节点的构造函数,将父字段直接作为对象传入。

代码语言:txt
复制
class TreeNode {
  constructor(id, value, parent) {
    this.id = id;
    this.value = value;
    this.parent = parent instanceof TreeNode ? parent : null;
    this.children = [];
  }
}

这样,节点的构造函数将接受一个父节点对象,而不是一个父节点的ID。在生成树的过程中,我们需要稍作修改来处理这种变化。

代码语言:txt
复制
function generateTree(nodes, parentField) {
  // 创建一个空的节点映射表,用于根据id查找节点
  const nodeMap = {};

  // 构建节点映射表
  for (const node of nodes) {
    nodeMap[node.id] = new TreeNode(node.id, node.value);
  }

  // 构建树结构
  for (const node of nodes) {
    const parentNode = node[parentField];
    const currentNode = nodeMap[node.id];

    // 将当前节点添加到父节点的子节点列表中
    if (parentNode) {
      const parent = nodeMap[parentNode.id];
      if (parent) {
        parent.children.push(currentNode);
        currentNode.parent = parent;
      }
    }
  }

  // 返回根节点
  return Object.values(nodeMap).find(node => !node.parent);
}

使用示例:

代码语言:txt
复制
const nodes = [
  { id: 1, value: 'A', parent: null },
  { id: 2, value: 'B', parent: { id: 1 } },
  { id: 3, value: 'C', parent: { id: 1 } },
  { id: 4, value: 'D', parent: { id: 2 } },
  { id: 5, value: 'E', parent: { id: 2 } },
  { id: 6, value: 'F', parent: { id: 3 } },
];

const tree = generateTree(nodes, 'parent');
console.log(tree);

输出结果:

代码语言:txt
复制
TreeNode {
  id: 1,
  value: 'A',
  parent: null,
  children: [
    TreeNode { id: 2, value: 'B', parent: [Circular], children: [Array] },
    TreeNode { id: 3, value: 'C', parent: [Circular], children: [Array] }
  ]
}

这样,我们通过递归算法从数组生成了一棵树,并且将父字段的表示形式更改为了对象而不是ID。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

前端工程师的vue面试题笔记

v-for>和 非 v-for节点上key用法已更改在同一元素上使用的 v-if 和 v-for 优先级已更改v-bind="object" 现在排序敏感v-for 中的 ref 不再注册 ref 数组... 没有特殊指令的标记 (v-if/else-if/else、v-for 或 v-slot) 现在被视为普通元素,并将生成原生的 元素,而不是渲染其内部内容。...会经历以下阶段:生成AST树优化codegen首先解析模版,生成AST语法树(一种用JavaScript对象的形式来描述整个模板)。...在这一层,前端开发者对从后端获取的 Model 数据进行转换处理,做二次封装,以生成符合 View 层使用预期的视图数据模型。...会经历以下阶段:生成AST树优化codegen首先解析模版,生成AST语法树(一种用JavaScript对象的形式来描述整个模板)。

68630
  • 拒绝重复代码,封装一个多级菜单、多级评论、多级部门的统一工具类

    tree_path 字段可以使用路径字符串表示节点的层级关系,例如使用逗号分隔的节点ID列表。这样,可以通过模糊匹配tree_path 字段来查询某个节点的所有子节点或父节点,而无需进行递归查询。...tree_path 字段的长度可能会随着树的深度增加而增加,可能会占用更多的存储空间。...因此,在设计数据库评论字段时,需要权衡使用treepath字段和父评论ID字段的优缺点,并根据具体的应用场景和需求做出选择。...如果你更关注读取操作的效率和查询、删除的灵活性,可以考虑使用tree_path 字段。...如果你更关注写入操作的效率和数据一致性,并且树的深度不会很大,那么使用父评论ID字段来实现多级评论可能更简单和高效。

    5300

    vue源码分析-插槽原理

    _u函数封装成数组的形式,并赋值到scopedSlots属性中,而每一个插槽以对象形式描述,key代表插槽名,fn是一个返回执行结果的函数。...10.3.2 父组件vnode生成阶段照例进入父组件生成Vnode阶段,其中_u函数的原形是resolveScopedSlots,其中第一个参数就是插槽数组。...而最终的核心是执行nodes = scopedSlotFn(props),也就是执行function(){return [_c('span',[_v("头部")])]},具名插槽之所以是函数的形式执行而不是直接返回结果...回过头看看为什么具名插槽是函数的形式执行而不是直接返回结果。...10.4.3 思考作用域插槽这个概念一开始我很难理解,单纯从定义和源码的结论上看,父组件的插槽内容可以访问到子组件的数据,这不是明显的子父之间的信息通信吗,在事件章节我们知道,子父组件之间的通信完全可以通过事件

    73430

    镜之Json Compare Diff | 技术创作特训营第一期

    因公司业务功能当中有一个履历的功能,它有多个版本的JSON数据需要对比出每个版本的不同差异节点并且将差异放置在一个新的JSON当中原有结构不能变动,差异节点使用数组对象的形式存储,前端点击标红即可显示多个版本的节点差异数据如下图图片图片示例...contact.668 也是新增的 phone 字段是修改了的对比后的Json// 获取差异的节点 使用数组对象表示{"employee/fullName/": [{"old": "John Miles...如果父节点是数组,则移除指定索引处的元素;否则,从对象中移除指定属性。- 如果值不为 null,它会检查值是否为数组。...如果是数组,它会创建一个新的 JSON 数组节点,并根据属性是否已存在,要么替换要么添加到父节点中。如果值不是数组,则根据其类型(布尔值、数字、字符串或 JSON 对象)更新 JSON 结构中的属性。...【写作提纲】一、前言因公司业务功能当中有一个履历的功能,它有多个版本的JSON数据需要对比出每个版本的不同差异节点并且将差异放置在一个新的JSON当中原有结构不能变动,差异节点使用数组对象的形式存储,前端点击标红即可显示多个版本的节点差异数据二

    58681

    前端基础精简总结

    ,即编译时加载 CMD和AMD是在运行时确定依赖关系,即运行时加载 详情: AMD && CMD ES6 模块化 每一个ES6模块都是一个包含JS代码的文件,模块本质上就是一段脚本,而不是用module...新增解构赋值、rest语法、箭头函数 这些都是为了让代码看起来更简洁,而包装的语法糖。 新增模块化 这是JS走向规范比较重要的一步,让前端更方便的实现工程化。...对象,由于元素之间有层级关系,因此整个HTML代码解析完以后,会生成一个由不同节点组成的树形结构,俗称DOM树 document用于描述DOM树的状态和属性,并提供了很多操作DOM的API。...dom 树 渲染引擎开始解析 html 标签,并将标签转化为DOM节点,生成 DOM树; css文件请求 如果head 标签中引用了外部css文件,则发出css文件请求,服务器返回该文件,该过程会阻塞后面的解析...重绘 当渲染树中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,比如 background-color 从上面可以看出,回流必将引起重绘,而重绘不一定会引起回流 会引起重绘和回流的操作如下

    1.7K40

    前端高频vue面试题总结3

    如何从真实DOM到虚拟DOM涉及到Vue中的模板编译原理,主要过程:将模板转换成ast 树,ast 用对象来描述真实的JS语法(将真实DOM转换成虚拟DOM)优化树将ast 树生成代码Vue3有了解过吗... 没有特殊指令的标记 (v-if/else-if/else、v-for 或 v-slot) 现在被视为普通元素,并将生成原生的 元素,而不是渲染其内部内容。...(Vue的虚拟DOM节点),详细步骤如下:首先,通过compile编译器把template编译成AST语法树(abstract syntax tree 即 源代码的抽象语法结构的树状表现形式),compile...在这种模式下,组件树构成了一个巨大的"视图",不管在树的哪个位置,任何组件都能获取状态或者触发行为。另外,通过定义和隔离状态管理中的各种概念并强制遵守一定的规则,代码将会变得更结构化且易维护。...Object.defineProperty 本身有一定的监控到数组下标变化的能力,但是在 Vue 中,从性能/体验的性价比考虑,尤大大就弃用了这个特性。

    1.2K40

    滴滴前端一面常考vue面试题(持续更新中)_2023-03-13

    数组就是使用object.defineProperty 重新定义数组的每一项,那能引起数组变化的方法我们都是知道的,pop 、push 、shift 、unshift 、splice 、sort 、reverse...这七种,只要这些方法执行改了数组内容,我就更新内容就好了,是不是很好理解。...如何从真实DOM到虚拟DOM涉及到Vue中的模板编译原理,主要过程:将模板转换成ast 树,ast 用对象来描述真实的JS语法(将真实DOM转换成虚拟DOM)优化树将ast 树生成代码虚拟DOM实现原理...在这一层,前端开发者对从后端获取的 Model 数据进行转换处理,做二次封装,以生成符合 View 层使用预期的视图数据模型。...会经历以下阶段:生成AST树优化codegen首先解析模版,生成AST语法树(一种用JavaScript对象的形式来描述整个模板)。

    82320

    不存在的好叭~

    子进程从fork调用的位置开始执行,而父进程和子进程在fork调用之后的代码处继续执行。资源继承:子进程继承了父进程的大部分资源,包括打开的文件、文件描述符、信号处理器等。...说一下ConcurrentHashMap是如何实现的线程安全的?在 JDK 1.7 中它使用的是数组加链表的形式实现的,而数组又分为:大数组 Segment 和小数组 HashEntry。...在 JDK 1.7 中,ConcurrentHashMap 虽然是线程安全的,但因为它的底层实现是数组 + 链表的形式,所以在数据比较多的情况下访问是很慢的,因为要遍历整个链表,而 JDK 1.8 则使用了数组...覆盖索引优化:覆盖索引是指 SQL 中 query 的所有字段,在索引 B+Tree 的叶子节点上都能找得到的那些索引,从二级索引中查询得到记录,而不需要通过聚簇索引查询获得,可以避免回表的操作。...算法树的层次遍历输出树的最大宽度合并k个有序数组

    13700

    Yaffs_guts

    yaffs的解决方法是将这张大的映射表拆分成若干个等长的小表,并将这些小表组织成树的结构,方便管理。...为了行文方便,后文中将yaffs_Tnode这个指针数组称为“一组”Tnode,而将数组中的每个元素称为“一个”Tnode。树中的每个节点,都是“一组”Tnode。 先看映射树的节点的分配。...在32位的系统中,指针的宽度为32位,而chunk id的宽度为16位,因此相同大小的Tnode组,可以用来表示N个非叶Tnode(作为指针使用),也可以用来表示N * 2个叶子Tnode(作为chunk...由于这4组Tnode在内存中不一定连续,所以 我们需要另外一组Tnode,将其作为指针数组使用,这个指针数组的前4个元素分别指向4组Level0节点,而fStruct->top就指向这组作为指针数组使用的...函数首先检查在父目录中是否已存在同名文件,然后同样调用yaffs_CreateNewObject创建新对象。参数-1表示由系统自行选择对象id。

    1.1K100

    看文吃瓜:React遭遇V8性能崩溃的故事

    JavaScript 引擎可以为这类 number 选择一个在内存中最佳的表达方式来优化根据下标访问数组元素操作的性能。对于处理器的访问内存操作来说,数组下标必须是一个能用补码形式表达的数字。...用 Float64 的方式来表达数组下标是非常浪费的,因为引擎在每次访问数组元素时不得不在 Float64 和补码之间反复转换。 32 位补码表达形式不只在数组操作中很实用。...最后,我们将旧的 shape 标记为废弃的并且将其从转变树 (transition tree) 中摘除。...如果更改表示的字段不是链中的最后一个字段,则会出现更棘手的情况: const o = { x: 1, y: 2, z: 3, }; o.y = 0.1; 在这个例子中,V8 需要去寻找一个被称为...所有属性都被表达为Smi形式,而且最终的转变是将这个属性标记为不可扩展的扩展性转变。 现在我们需要将 y 修改为 Double 表达,意味着我们需要重新开始找到分离 shape。

    43240

    百度前端经典vue面试题整理5

    从本质上来说,Virtual Dom是一个JavaScript对象,通过对象的方式来表示DOM结构。将页面的状态抽象为JS对象的形式,配合不同的渲染工具,使跨平台渲染成为可能。...树,它是一种用 JavaScript对象的形式来描述整个模板。...(3)生成代码const code = generate(ast, options)generate将ast抽象语法树编译成 render字符串并将静态部分放到 staticRenderFns 中,最后通过...Object.defineProperty 本身有一定的监控到数组下标变化的能力,但是在 Vue 中,从性能/体验的性价比考虑,尤大大就弃用了这个特性。...会经历以下阶段:生成AST树优化codegen首先解析模版,生成AST语法树(一种用JavaScript对象的形式来描述整个模板)。

    81630

    H2 存储内核解析

    数据块(chunk) 数据块id,通常与版本号相同;但是,数据块id可能会回滚到0,而版本不会。...叶子页面包含Map的键值对,而内部节点只包含键和指向叶子页面的指针。树的根节点可以是叶子页面或内部节点。...keys (字节数组)数组存储了该节点的所有键,类型取决于数据类型 values (字节数组)(仅适用于叶子节点)存储了该节点的所有值,类型取决于数据类型 尽管文件格式不要求这样做...长度代码是从0到31的数字,其中0表示页面(page)的最大长度为32个字节,1表示48个字节,2表示64,3表示96,4表示128,5表示192,以此类推,直到31表示超过1 MB。...说明一点:有些朋友有疑问,为什么 DawnSql 选择 h2 的存储内核,而不是去重新做一个?这里主要是为了高用性!h2 作为成熟的数据库存储内核,已经在实际的项目中应用了多年,它是经得起考验的。

    58870

    vue面试经常会问的那些题

    props属性名规则:若在props中使用驼峰形式,模板中需要使用短横线的形式// 父组件 id="father"> 父组件传值$emit绑定一个自定义事件,当这个事件被执行的时就会将参数传递给父组件,而父组件通过v-on监听并接收参数。...会经历以下阶段:生成AST树优化codegen首先解析模版,生成AST语法树(一种用JavaScript对象的形式来描述整个模板)。...key 是给每一个 vnode 的唯一 id,依靠 key,我们的 diff 操作可以更准确、更快速 (对于简单列表页渲染来说 diff 节点也更快,但会产生一些隐藏的副作用,比如可能不会产生过渡效果,...会经历以下阶段:生成AST树优化codegen首先解析模版,生成AST语法树(一种用JavaScript对象的形式来描述整个模板)。

    1K20

    Java数据结构和算法(十)——二叉树

    树有很多种,向上面的一个节点有多余两个的子节点的树,称为多路树,后面会讲解2-3-4树和外部存储都是多路树的例子。而每个节点最多只能有两个子节点的一种形式称为二叉树,这也是本篇博客讲解的重点。   ...  上图的第一幅图B节点有DEF三个子节点,就不是二叉树,称为多路树;而第二幅图每个节点最多只有两个节点,是二叉树,并且二叉树的子节点称为“左子节点”和“右子节点”。...①、删除没有子节点的节点   要删除叶节点,只需要改变该节点的父节点引用该节点的值,即将其引用改为 null 即可。...如果不是根节点,是叶节点,那么断开父节点和其的关系即可。   ②、删除有一个子节点的节点   删除有一个子节点的节点,我们只需要将其父节点原本指向该节点的引用,改为指向该节点的子节点即可。 ?...9、用数组表示树    用数组表示树,那么节点是存在数组中的,节点在数组中的位置对应于它在树中的位置。

    1.6K60
    领券