方案设计反思一
故事起源于老婆与我探讨的一个解决方案。
琳:“有一个问题,我有几百个表情符号,这种文本的[xx]。我选出来正向表情10个,负想表情10个。然后选择只含有这正向表情的微博和只含有负向表情的微博。这个怎么做呢?我之前选的的微博都混在一起了。” 苏遇:“你是说要挑出含表情符号的微博?” 琳:“嗯。” 苏遇:“把微博一条一条的读进来,如果包含表情符号,就保存。” 琳:“是。你仔细看我的问题,只含有正向那10个,怎么挑?” ……
说了半天,我确实是没有看懂老婆提出的问题。最终老婆是想选择只含有这正向表情的微博和只含有负向表情的微博,只含有的意思是不包含其他中立表情等等。于是我给出的解决方案是:先判断是否包含中立表情;如果是,退出当前逻辑(也许是一个函数);如果不是,则判断是否含有正向或者负向的表情;如果是,则保存;不是,则退出当前逻辑。
接着,老婆说中立表情符号几百个呢,正向负向表情都是10个。
在后面的交谈中,我反思出了几个问题。老婆提出的这个问题背景,首先的一点是按照之前的解决方案,我们需要花费很大的人力去把几百个中立表情符号弄到程序里去。或者是先保存在磁盘上,或者是直接硬编码到程序中。当然不管无论如何,我们都难以避免枯燥乏味的并且是程序员最讨厌,却又最常做的一件事情,那就是复制粘贴。潜在的还有一个问题就是效率的问题。因为老婆可能需要处理几千万条微博。这里只是可能,毕竟我们只是做实验,当然可以偷懒,也就是偷偷的去掉几个零。首先每一条微博读到程序中之后,需要对几百个表情符号进行一一判定,时间复杂度直接就是 (Nmicroblog)*(Nemotion)*(log AVG length of microblog)。查找的复杂度就是算微博平均长度的对数值。而面对几千万条微博而言,也许我们可以好几天不用来实验室了,在寝室好好的休息几天。
我想了半天没有任何思绪来优化。因为我们的需求已经说明了,必须要查找中立表情,然后再查找正向负向表情。真的就没有优化方案了吗?只是因为我把自己的思维定死在需求上了,而没有去真正的设计一个解决方案。接下来,老婆说的一句话成为了亮点。
琳:“排除正负表情,其他都是中立。” 苏遇:“恩,那就按你刚才这句话做。”
确实,当我听到这句话的时候,就恍然大悟了。其实我们的需求本质上是3个条件判断,我们只要调整好条件判断的顺序就可以事半功倍。我们先判断一条微博是否含有正向表情,然后判断是否含有负向表情,最后呢?当然不是去判断是否含有中立表情。优化的解决方案有一个关键步骤,就是我们需要把微博中的表情提取出来。表情符号在文本中有一定的格式,即[**]这种格式。我们可以使用正则表达式来提取这些表情符号,然后经过正向表情和负向表情的判定之后,就可以了。因为除了正负表情,它就是中立表情。于是乎,世界忽然之间就一切太平了。
只是,这该死的正则表达式几乎要让我癫狂了。因为我基本不会写。不过最后还是碰巧试对了。
Pattern p = Pattern.compile("(\\[[^\\]]{1,3}\\])",Pattern.CASE_INSENSITIVE + Pattern.MULTILINE);
这个问题也没这样简单的就结束了。因为它一直在我脑海中回荡。在上厕所的时候,我还想到了另外一种解决方案。其思路没有变化,只是用上了一些高级的工具。或者我们可以使用Hadoop来解决它。