Python:将复合词拆分为已知词(来自字典)

3 投票
2 回答
3327 浏览
提问于 2025-05-10 09:57

我需要一个非常高效的算法来完成以下任务:

我需要把复合词分开,任何语言都可以,比如英语。

但是有一个问题,当一个词是由两个词组成,并且这两个词的最后一个字母和第一个字母相同的时候,就会出现问题。

也就是说,第一个词的结尾字母正好是第二个词的开头字母。

我们有一个字典,里面包含所有可能的单词,简单来说:

假设我们想把“lightshow”这个词分开,使用这个示例字典:

d = {"light": "Noun, S, N",
    "lights": "Noun, P, N",
    "how": "Q",
    "show": "Noun, S, N",
    ...}

我的算法现在把这个词分成两部分,放到两个列表里:

left = []; right = []
for x in range(len(word)-1, 1, -1):
    ls = word[:x]; rs = word[x:]
    if ls.lower() in d: left.append(ls)
    if rs.lower() in d: right.append(rs)

然后我会在左边和右边的列表中找到最长的单词。

这样,我就知道这个词是由哪些单词组成的,以及它们在复合词中的起始和结束位置。

现在不用担心那些复杂的情况,比如词不在字典里,或者单词不匹配等等,我只是想给你展示这个思路,以及我在这个方法上遇到的最大问题。

使用这种方法,最后算法的结果会是:

["lights", "how"]

而不是:

["light", "show"]

这显然是不可接受的。

哦,对了,我可以检查字典里是否有“show”这个词,方法是:

l = ["lights", "how"]
if l[0][-1]+l[1] in d: <repair the list>

但这并不实用,而且我的算法还要递归处理由多个词组成的单词。

它还处理那些因为大小写不同而分开的单词等等。

所以我没有把整个代码贴出来,因为它很大而且已经优化过,贴出来会有很多不重要的代码。

哦,对了,我可以通过把最后一个词作为优先来做一些改进,或者在选择哪个词先出现时比较长度等等。

但这些操作并不总是能正确决定。例如,遇到多个字母重叠的最长单词该怎么办?

我想在一个循环里完成这一切,速度是关键。

注意:我提供的字典只是示例。我需要处理的数据集并没有包含单词的类型信息。只有发音的信息,能用来判断单词是短还是长。

希望能在这里看到一些很好的想法。记住,代码必须非常高效。它是实时使用的,目的是让文本转语音(TTS)读出那些不在字典里的词,但实际上包含了字典里的词,而且通常发音是匹配的。

不需要给我提供代码,只需要一些可以付诸实践的想法。

相关文章:

  • 暂无相关问题
暂无标签

2 个回答

2

我脑海中立刻想到两个因素,不过你可能还是需要先用你的数据集来验证一下。

  1. 按词性加权。通常,复合词里会有名词,所以如果你在选择 N + QN + N 时,可能 N + N 是更正确的选择。我一时想不到有什么情况会更倾向于非名词的词,但这正是你应该检查的地方。
  2. 按单数和复数加权。尤其是在中间有“s”的情况下,通常这个“s”是复数形式,所以在选择时更倾向于 S + X 而不是 P + X
3

在这种情况下,你可以根据连字符算法或字典建议的音节断开方式来处理单词。一个好的连字符算法会告诉你,像 light-showdata-set 这样的单词是正确分开的。

不过,我觉得要在每一种情况下都做到完美是很难的,除非你有一个数据文件,明确把 lightshow 映射到 light + show,把 dataset 映射到 data + set,等等。无论你设计什么算法,总会有一些例外情况,它会出错。

Frank Liang 的连字符算法 在这里可以找到,适用于 Python,它能帮助你处理你提到的两个例子中的一个:

>>> hyphenate_word("dataset")
['dataset']
>>> hyphenate_word("lightshow")
['light', 'show']

你可以尝试测试 hyphenate_word() 返回的音节组合(这个函数应该很高效,因为它在 TeX 中使用),如果没有找到合适的组合,就试试你最初的方法。

在这些单词上,它的表现相当不错:

 [hyphenate_word(x) for x in ["backwoodsman", "whatsoever", "hereupon", "counterclockwise", "notwithstanding", "highwayman "]]
[['back', 'woods', 'man'], ['what', 'so', 'ev', 'er'], ['here', 'upon'], ['coun', 'ter', 'clock', 'wise'], ['notwith', 'stand', 'ing'], ['high', 'way', 'man ']]

这里有一个方便的复合词列表,还有一些 三重复合词

撰写回答