修正用户消息中的重复字母
我在分析社交媒体或聊天中的信息时,常常遇到一种特殊的拼写错误,就是人们用重复的字母来表达情感或其他意思,比如:
"wowwwwww!"
"Daaaaaaamn!"
"I'm soooooo pisssssed"
我在想有没有一种比较靠谱的方法来纠正这些情况。
为了把重复的字母(重复三次或更多)替换成只有两个字母的形式,我已经找到了合适的正则表达式:
s = re.sub(r'(.)\1+', r'\1\1', s)
不过根据上面的例子,这样处理后会变成:
"woww!"
"Daamn!"
"I'm soo pissed"
这样看起来好一些,但还不够完美。我该怎么决定在什么时候用一个字母替代两个字母呢?
一种(可能有点天真的)方法是用一个字典来检查哪个版本在字典里。或者也许有一些简单的语言规则可以用来判断什么时候需要双字母。或者可能还有更好的方法来解决这个问题。
编辑:根据所有的回答,我想出了一个看起来还不错的解决方案。
- 使用了Ubuntu的
/usr/share/dict/words
作为字典 - 用
Soundex
(和其他类似算法)对所有字典中的单词进行了索引 - 对于每个输入的单词,我会 (a) 检查它是否在索引中,如果不在的话 (b) 检查所有发音相似的单词,并选择与输入单词相似度最高的那个——注意,在这个初步步骤中,先把所有重复两个以上的字母替换成两个字母
- 在少数情况下,如果我得到多个相似度最高的结果(例如,
wooww
结果是wow
和woo
同样相似),我会利用 Typoglycemia 的概念,根据首字母和尾字母的相似度来判断
通过这个解决方案,我不仅很好地解决了重复字母的问题,还能处理一般的拼写错误。虽然可能还远远不够完美,但从另一方面来看,这也是一个非常简单的解决方案。
3 个回答
如果“拼写错误的内容”比较少,或许可以提供一些专门的规则?
>>> rules = (('wo+w+', 'wow'), ('da+m+n+', 'damn'), ('so+', 'so'),('coo+l+','cool'))
# in "real world", should compile the regex for obvious performance reasons
>>> s = 'wowwww sooo cool'
# in "real world", normalize somehow (lowercase?)
>>> for pattern, replace in rules:
... s = re.sub(r'\b'+pattern+r'\b', replace, s)
...
>>> s
'wow so cool'
不过这会涉及很多组合!另一方面,可能不太难进行并行处理。
为了提高性能,或许可以用 lexer 来写一个程序,使用 PLY
?不过这次你还是需要为每个单词提供专门的规则,但主要的好处是每个字符只会被检查一次。缺点是这样就不容易进行并行处理了(据我所知)。
可能有一种方法可以使用词汇表和最小编辑距离(MED)来解决这个问题。
我们来看看一个不在词汇表中的单词:'daaaaamn'。将'daaaaamn'变成'damn'的最小编辑距离是3(需要删除三个字母)。
现在,你可以调整这个编辑距离的计算方式,让删除的成本更低。比如,你可以设定插入一个字母的成本是1,替换一个字母的成本也是1,而删除一个字母的成本是0.5(这样编辑距离变成了1.5)。或者,如果你已经在一串字母中删除了相同的字母,可以把删除的成本设为0(这时编辑距离变成1)。
接下来,你只需要选择那个编辑距离最小的单词(希望是'damn')。
因为你可以尝试很多不同的设置,所以你可能想要建立一些参考数据,看看哪种方法效果最好。
祝你好运。
最近,我发了一篇关于最小编辑距离的帖子,可以在这里找到:无法理解最小编辑距离的直觉