首页
学习
活动
专区
工具
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对象形式来描述整个模板)。

68130
  • vue源码分析-插槽原理

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

    71830

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

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

    53181

    前端基础精简总结

    ,即编译时加载 CMD和AMD是在运行时确定依赖关系,即运行时加载 详情: AMD && CMD ES6 模块化 每一个ES6模块都是一个包含JS代码文件,模块本质上就是一段脚本,不是用module...新增解构赋值、rest语法、箭头函数 这些都是为了让代码看起来简洁,包装语法糖。 新增模块化 这是JS走向规范比较重要一步,让前端方便实现工程化。...对象,由于元素之间有层级关系,因此整个HTML代码解析完以后,会生成一个由不同节点组成树形结构,俗称DOM document用于描述DOM状态和属性,并提供了很多操作DOMAPI。...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对象形式来描述整个模板)。

    81620

    不存在好叭~

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

    13400

    看文吃瓜: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。

    42440

    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

    1K100

    百度前端经典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对象形式来描述整个模板)。

    80830

    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 作为成熟数据库存储内核,已经在实际项目中应用了多年,它是经得起考验

    57970

    vue面试经常会问那些题

    props属性名规则:若在props中使用驼峰形式,模板中需要使用短横线形式// 组件 <son :msg="msgData" :fn...子组件向组件传值$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.5K60

    30 道 Vue 面试题,内含详细讲解(涵盖入门到精通,自测 Vue 掌握程度)

    $emit("mounted"); } 以上需要手动通过 $emit 触发组件事件,简单方式可以在组件引用子组件时通过 @hook 来监听即可,如下所示: // Parent.vue <Child...Mutation:是唯一更改 store 中状态方法,且必须是同步函数。 Action:用于提交 mutation,不是直接变更状态,可以包含任意异步操作。...在这一层,前端开发者对后端获取 Model 数据进行转换处理,做二次封装,以生成符合 View 层使用预期视图数据模型。..., Object.defineProperty 只能遍历对象属性直接修改; Proxy 作为新标准将受到浏览器厂商重点持续性能优化,也就是传说中新标准性能红利; Object.defineProperty...,通过这个 key,我们 diff 操作可以准确、更快速 准确:因为带 key 就不是就地复用了,在 sameNode 函数 a.key === b.key 对比中可以避免就地复用情况。

    1.6K31
    领券