23

使用代码列出金庸小说中使用过的所有成语 - Jerry Wang的SAP技术专栏 - SegmentFault...

 4 years ago
source link: https://segmentfault.com/a/1190000020901343
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

使用代码列出金庸小说中使用过的所有成语

去年的今天,金庸与世长辞,当时Jerry在成都地铁一号线下班的路上得知了这个消息,回到家立即写了一篇文章来悼念:金庸的武侠世界和SAP的江湖

一年的时间转瞬即逝,大家都忙碌于各自的生活,很多人对金老的离世已经淡忘了,不过Jerry这种金庸的死忠粉,对于这个一周年忌日还是记得很清楚的。

因为Jerry手上事情很多,没时间在这个特殊的日子写文章纪念了,就发一小段代码吧。

需求:列出金庸任意一本小说里出现的所有成语。

实现:Jerry部署在Github上的一个web应用,链接如下:

http://jerrywang-sap.cn/Fiori...

首先点击超链接“成语全集”:

clipboard1,1

点击之后,存储于该web应用本地存储的一个文本文件里的全部19830个成语,以树的形式加载到内存中,并显示在网页上:

clipboard2,2

然后复制一本金庸小说的内容,粘贴到网页的“内容”区域,点击按钮“测试”:

clipboard3,3

可以看到仅仅用了246毫秒,就将这部一百多万字的《倚天屠龙记》里出现的所有成语,以红色高亮的方式高亮出来。

clipboard4,4

这个功能咋实现的?Chrome打开Jerry的网页,F12开启开发者工具,就能看到JavaScript源代码,当然也可以从我的Github上获得.

Jerry简单讲下实现原理。Web应用里有一个文本文件,里面维护了汉语里全部的成语,通过分号分隔。

clipboard5,5

运行时,这些内容会被加载到内存中,构建成一棵树,如下图所示:

clipboard6,6

其中叶节点以属性end为true区分。

成语检索的核心逻辑位于search函数里,让我们用《笑傲江湖》里一句响亮的口号“日月神教千秋万载,一统江湖”来单步调试,了解其实现逻辑。

clipboard7,7

进入165行的外层while循环,再进入173行的内层for循环,检测是否有测试字符串第一个字符“日”开头的成语。因为成语是由4个字符组成,所以需要用内层for循环逐一试探,如果遇到tblCur.end为true的元素,说明在测试字符串中发现了一个成语。

下图是内层for循环第一次执行后的tblCur内容:

clipboard8,8

内层循环执行第二次,此时tblCur指向一棵由所有“日月”开头的成语组成的树:

clipboard9,9

执行内层循环的第三次迭代,因为在树“日-月”这个分支下面没有“神”这个节点,所以结束当前的内层循环,通过break返回到外层的while循环,进行输入字符串第二个字符“月”的新一轮试探,以此类推。

clipboard10,10

最后从“千”这个字符出发,沿着内存中的树经过路径"秋-万",最后来到end属性为true的叶节点“载”,记下“千”在输入字符串中的偏移量,存到一个数组arrMatch中去。

clipboard11,11
clipboard12,12

待输入字符串全部试探完毕后,根据arrMatch中存放的偏移量,高亮显示对应的字符串,完成检索。

clipboard13,13
树这个数据结构在这个需求的实现里有着完美的表现。

金庸虽然离开了我们,但他笔下那些人物和发生的故事,将永远流传于这个世上。

要获取更多Jerry的原创文章,请关注公众号"汪子熙":
公众号截图


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK