最近在写一个博客的小项目,对接github的钩子,当提交markdown工程至github时,通过设置github的钩子,程序获取提交的markdown源码,包括新增,更新,删除的文件列表,然后将其拉取到数据库。前端解析markdown文本至html页面展示。
中间遇到一个很有意思的问题:目录的解析。
markdown的目录结构可能如下:前端/js/you_dont_konw_js
,前端/js/node_at_scale
,前端/css
等等。我在解析的时候,将其解析成数组:[['前端','js','your_dont_konw_js'],['前端','js','node_at_scale'],['前端','css']]
,其中的每一项表示每个文件所在的目录。
在有一个分类的页面中,我想将每个目录中文档个数统计出来,并想展示其目录结构,预期如下:
从数据库中查出来的原始数组如下:
1 | let catalogs = |
其实统计文档数目很简单:
1 | let obj = {}; |
先将二维数组扁平化到一维,然后进行统计即可,输出的结果:
1 | { ComputerSystem: 4, |
这里统计好了每个目录里总文档的个数,但是有个问题是,目录之间没有层级关系,在页面上展示时,不好展示。
这里抽象一下的话,目录应该是一个树形的结构,因此,很容易想到使用一个树结构。
第一次,写了一个函数,由上面这个数组,生成一个树型结构对象:
1 | /** |
跑一下,扔出来的结构:
1 | { |
这个函数虽然实现了功能,但是逻辑混乱,另外效率也不高。
每个元素的插入要指定其父元素,每次都得从头查找父元素,所以效率不高。而且每次查找逻辑都冗余在插入逻辑中,混乱。
可以将这个树抽象成一个树对象,将查找,插入等等抽象成其方法。
但是,由于每个目录有多个子目录,因此,不能用简单的二叉树。
改完的树类:
1 | let find = (item, tree) => { |
其中,查找方法使用广度遍历,使用队列。
插入的时候,每次查找不再从树根开始查找,而是从找到的父目录的子树开始查找,效率比第一个函数方式要稍微高点。
虽然在这种简单的项目上,目录也不是很多,效率什么的并不明显,但是能考虑的地方就要多考虑考虑。
刚才说过了,不能使用二叉树,那么多叉树,也能用图进行抽象。但是图有个问题是,不好处理层级之间的关系,也就作罢。
就先这样吧,仓促之余先写这么多,等有时间再想想有没有其他更好的方法。