构建决策树的算法_一个简单的树构建算法

构建决策树的算法

In this article, I will show you a simple JavaScript algorithm to build a tree, using functional programming.

在本文中,我将向您展示一种使用函数式编程来构建树的简单JavaScript算法。

Also available in french

也提供 法语

In my journey of developing Naept, I encountered the need to build trees. An easy example of what is a tree, are the chapters of a document. If the document is the trunk, all the main chapters are the branches of that tree. And all those main chapters may be divided into sub-chapters, which may be, in turn, again sub-divided in sub-sub-chapters, and so on…

在开发Naept的过程中 ,我遇到了建造树木的需求。 一个简单的例子就是文档的各章。 如果文档是主干,则所有主要章节都是该树的分支。 并且所有这些主要章节都可以分为子章节,而子章节又可以细分为子子章节,依此类推……

在数据库内部 (Inside the database)

The most simple thing to do when storing objects that constitute a tree inside a database is giving them a link to their parent.

在数据库中存储构成树的对象时,最简单的操作是为其提供指向其父级的链接。

Image for post

So each one of my chapters has a parent_id property. And if this parent_id's value is null for some elements, that means that they are each the root element of a tree.

所以我的每一章都有一个parent_id属性。 并且如果某些元素的parent_id值为null ,则意味着它们都是树的根元素。

Image for post

So from this point, in theory, we should be able to “build a tree”, and what I mean by that is creating a software representation of this tree:

因此从理论上讲,从这一点出发,我们应该能够“构建一棵树”,而我的意思是创建该树的软件表示形式:

Image for post

Yes, I know my tree is weird, growing from the left to the right instead of growing up. But you get the idea!

是的,我知道我的树很奇怪,从左到右生长而不是长大。 但是你明白了!

功能编程方法 (A functional programming approach)

I’ve not always been a JavaScript programmer. I’ve actually started very low, abstraction-wise. Like Assembly, C, even VHDL. I’ve been introduced to Object-Oriented Languages with C++ more than a decade ago and I’ve loved it. But with JavaScript, I’ve developed an interest in functional programming, and I wanted to solve this problem with functional programming.

我并非一直是JavaScript程序员。 实际上,我从抽象的角度开始很低。 像Assembly,C甚至VHDL。 十多年前,我已经将C ++引入了面向对象的语言,并且我很喜欢它。 但是,通过JavaScript,我对函数式编程产生了兴趣,并且我想通过函数式编程解决此问题。

So, let’s get back on track.

因此,让我们回到正轨。

Each of these Chapter objects potentially has Chapter objects as it's children (sub-chapters). And each of these children Chapter objects may have children of their own, and so on... While reading this you may see a pattern emerges in your mind. Recursion!

这些Chapter对象中的每个对象都可能具有Chapter对象作为其子对象(子章)。 每个这些子Chapter对象可能都有自己的子对象,依此类推...阅读本文时,您可能会发现脑海中浮现出一种模式。 递归!

I’ve always loved recursion. It’s one of the beauties of programming. And for once, it’s not an imitation of nature. It is unique to programming. Recursion cannot be found in nature (or perhaps fractals may come close ?).

我一直很喜欢递归。 这是编程的美丽之一。 而且这不是对自然的模仿。 它是编程所独有的。 在自然界中找不到递归(或者分形可能接近吗?)。

Image for post

Anyway, the idea of our algorithm will be to recursively build a tree, sub-tree by sub-tree, using recursion and functional programming.

无论如何,我们算法的思想是使用递归和函数式编程,以子树的方式递归地构建一棵树。

让我们编码吧! (Let’s code!)

First, the chapters. Let’s say we have an array of objects, each object being one chapter :

首先,各章。 假设我们有一个对象数组,每个对象都是一个章节:

let chapters = [
{
id: 1,
parent_id: null,
text: 'Chapter 1',
},
{
id: 2,
parent_id: null,
text: 'Chapter 2',
},
{
id: 3,
parent_id: null,
text: 'Chapter 3',
},
{
id: 4,
parent_id: 1,
text: 'Chapter 1.1',
},
{
id: 5,
parent_id: 1,
text: 'Chapter 1.2',
},
{
id: 6,
parent_id: 1,
text: 'Chapter 1.3',
},
{
id: 7,
parent_id: 3,
text: 'Chapter 3.1',
},
{
id: 8,
parent_id: 3,
text: 'Chapter 3.2',
},
{
id: 9,
parent_id: 5,
text: 'Chapter 1.2.1',
},
{
id: 10,
parent_id: 5,
text: 'Chapter 1.2.2',
},
{
id: 11,
parent_id: 7,
text: 'Chapter 3.1.1',
},
{
id: 12,
parent_id: 7,
text: 'Chapter 3.1.2',
},
]

The idea is to get this structure out of the algorithm :

想法是使这种结构脱离算法:

[
{
id: 1,
parent_id: null,
text: "Chapter 1",
children: [
{
id: 4,
parent_id: 1,
text: "Chapter 1.1",
children: []
},
{
id: 5,
parent_id: 1,
text: "Chapter 1.2",
children: [
{
id: 9,
parent_id: 5,
text: "Chapter 1.2.1",
children: []
},
{
id: 10,
parent_id: 5,
text: "Chapter 1.2.2",
children: []
}
]
},
{
id: 6,
parent_id: 1,
text: "Chapter 1.3",
children: []
}
]
},
{
id: 2,
parent_id: null,
text: "Chapter 2",
children: []
},
{
id: 3,
parent_id: null,
text: "Chapter 3",
children: [
{
id: 7,
parent_id: 3,
text: "Chapter 3.1",
children: [
{
id: 11,
parent_id: 7,
text: "Chapter 3.1.1",
children: []
},
{
id: 12,
parent_id: 7,
text: "Chapter 3.1.2",
children: []
}
]
},
{
id: 8,
parent_id: 3,
text: "Chapter 3.2",
children: []
}
]
}
]

Each node (chapter) is given a children attribute. This attribute is an array containing the node's children (sub-chapters).

每个节点(每章)都被赋予一个children属性。 该属性是一个包含节点的子代(子章节)的数组。

So what our algorithm will do is, being given the whole array of nodes, and the id of the parent node:

因此,我们的算法将要执行的工作是,获得整个节点数组以及父节点的id

  • filter the array to keep only the nodes with the given parent_id;

    过滤数组以仅保留具有给定parent_id的节点;

  • return an array of those nodes, and in each of them we add a children attribute, which is an array, and this array is built using a function that, being given the whole array of nodes, and the id of the current node as the parent_id argument, will:

    返回这些节点的数组,并在每个节点中添加一个children属性,这是一个数组,并且使用给定节点的整个数组并将当前节点的id作为函数的函数构建此数组。 parent_id参数将:

  • filter the array to keep only the nodes with the given parent_id;

    过滤数组以仅保留具有给定parent_id的节点;

  • return an array of those nodes, and in each of them we add a children attribute, which is an array, and this array is build using a function that, being given the whole array of nodes, and the id of the current node as the parent_id argument , will:

    返回这些节点的数组,并在每个节点中添加一个children属性,这是一个数组,并且使用给定节点的整个数组并将当前节点的id作为函数的函数构建该数组。 parent_id参数,将:

  • filter the array to keep only the nodes with the given parent_id;

    过滤数组以仅保留具有给定parent_id的节点;

  • return an array of those nodes, and in each of them we add a children attribute, which is an array, and this array is built using a function that, being given the whole array of nodes, and the id of the current node as the parent_id argument, will:

    返回这些节点的数组,并在每个节点中添加一个children属性,这是一个数组,并且使用给定节点的整个数组并将当前节点的id作为函数的函数构建此数组。 parent_id参数将:

  • …well, you get the idea…

    …反正你懂这个意思…

Here is how it translates into JavaScript:

这是如何转换成JavaScript的:

function makeTree(nodes, parentId) {
return nodes
.filter((node) => node.parent_id === parentId)
.reduce(
(tree, node) => [
...tree,
{
...node,
children: makeTree(nodes, node.id),
},
],
[],
)
}

Using the reduce function, which is emblematic of functional programming, we build the array of nodes of one level, adding the children array to each node and filling it up by calling the makeTree function.

使用reduce功能,这是象征函数编程的,我们建立一个水平的节点阵列,加入children阵列到每个节点,并通过调用它填充了makeTree功能。

Thanks for reading me. I hope you enjoyed this article. You can read the french version of it on the blog of my company, alongside a lot of other articles on documentation, which is what we do at Naept.

感谢您的阅读。 希望您喜欢这篇文章。 您可以在我公司博客上阅读它的法文版本,以及许多其他有关文档的文章,这是我们在Naept所做的

Please comment on this article and share your way of building trees, which is probably different.

请评论本文并分享您构建树木的方式,这可能有所不同。

Have a nice day!

祝你今天愉快!

Originally published at https://www.naept.com on September 7, 2020.

最初于 2020年9月7日 发布在 https://www.naept.com 上。

翻译自: https://medium.com/weekly-webtips/a-simple-tree-building-algorithm-naept-ebe95338d81b

构建决策树的算法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值