从文本中检测最可能的单词而不使用空格/组合单词

时间:2010-02-01 00:55:57

标签: python split word

是否有一个好的库可以检测并拆分组合字符串中的单词?

示例:

"cdimage" -> ["cd", "image"]
"filesaveas" -> ["file", "save", "as"]

7 个答案:

答案 0 :(得分:11)

这是一个动态编程解决方案(作为memoized函数实现)。给定具有其频率的单词字典,它将输入文本分割为给出总体最可能短语的位置。你必须找到一个真正的单词列表,但我为一个简单的测试包含了一些组合频率。

WORD_FREQUENCIES = {
    'file': 0.00123,
    'files': 0.00124,
    'save': 0.002,
    'ave': 0.00001,
    'as': 0.00555
}

def split_text(text, word_frequencies, cache):
    if text in cache:
        return cache[text]
    if not text:
        return 1, []
    best_freq, best_split = 0, []
    for i in xrange(1, len(text) + 1):
        word, remainder = text[:i], text[i:]
        freq = word_frequencies.get(word, None)
        if freq:
            remainder_freq, remainder = split_text(
                    remainder, word_frequencies, cache)
            freq *= remainder_freq
            if freq > best_freq:
                best_freq = freq
                best_split = [word] + remainder
    cache[text] = (best_freq, best_split)
    return cache[text]

print split_text('filesaveas', WORD_FREQUENCIES, {})

--> (1.3653e-08, ['file', 'save', 'as'])

答案 1 :(得分:8)

我不知道它的任何库,但实现基本功能应该不难。

  1. 获取单词列表,例如UNIX的words
  2. 将单词列表的内容填入特里。
  3. 取出要拆分的字符串并按照其中的路径进行操作。每次到达有效单词时,创建一个新分支,从您到达的字符串的点开始搜索单词。完成当前分支后,回溯到您创建的分支,就像在深度优先搜索中一样。
  4. 使用启发式或自然语言解析器手动消除结果列表的歧义。
  5. 示例:

    1. Word:“filesaveasstring”
    2. 第一个有效单词是“file”。尝试匹配“saveas”。第一个有效的词是“保存”。尝试匹配“asstring”。第一个有效单词是“as”。尝试匹配“字符串”。第一个有效字是“字符串”。匹配到结束;将[file save as string]放入结果列表。
    3. 回溯到匹配“字符串” - 没有其他可能性。回溯到“asstring”。第一个未经访问的有效词是“屁股”。尝试匹配“tring”。没有可能的比赛。回溯到“asstring”。没有可能的比赛。回溯到“filesaveasstring”。
    4. 第一次未访问的比赛是“文件”。尝试匹配“aveasstring”。第一场比赛是“大道”。尝试匹配“asstring”(与步骤2/3相同的结果),将[file ave as string]添加到结果列表并回溯到开头。
    5. 尝试匹配“filesaveasstring”。没有未经访问的比赛。完成。
    6. 使用启发式或自然语言解析器从[[file save as string] [files ave as string]]中选择最有可能。

答案 2 :(得分:3)

让人们在您的网站上将其解析为验证码:)

答案 3 :(得分:2)

我不知道这样做的库,但如果你有一个单词列表,写起来并不难:

wordList = file('words.txt','r').read().split()
words = set( s.lower() for s in wordList )

def splitString(s):
    found = []

    def rec(stringLeft, wordsSoFar):
        if not stringLeft:
            found.append(wordsSoFar)
        for pos in xrange(1, len(stringLeft)+1):
            if stringLeft[:pos] in words:
                rec(stringLeft[pos:], wordsSoFar + [stringLeft[:pos]])

    rec(s.lower(), [])
    return found

这将返回将字符串拆分为给定单词的所有可能方法。

示例:

>>> splitString('filesaveas')
[['file', 'save', 'as'], ['files', 'ave', 'as']]

答案 4 :(得分:2)

可以看到这个例子:但是它是用scala编写的。 当句子之间没有空格时,这可以拆分您想要的任何内容。

Nonspaced-Sentence-Tokenizer

答案 5 :(得分:-1)

如果你不是为了好玩而做这件事,但实际上是在为工作做些什么,我的建议是从源头上解决这个问题。为什么你把这些字符串组合起来呢?你从哪里得到那些琴弦?如果可能的话,在这些字符串的来源处插入空格。

答案 6 :(得分:-1)

我知道这个问题是针对Python标记的,但我需要一个JavaScript实现。离开之前的答案,我想我会分享我的代码。似乎工作得体。

function findWords(input){
    input = input.toLowerCase().replace(/\s/g, ""); //Strip whitespace

    var index = 0;
    var validWords = [];
    for (var len = input.length; len > 0; len--){ //Go backwards as to favor longer words
        var testWord = input.substr(index, len);
        var dictIndex = _dictionary.indexOf(testWord.replace(/[^a-z\']/g, "")); //Remove non-letters
        if (dictIndex != -1){
            validWords.push(testWord);
            if (len == input.length){
                break; //We are complete
            }
            var nextWords = findWords(input.substr(len, input.length - len)); //Recurse
            if (!nextWords.words.length){ //No further valid words
                validWords.pop();
            }
            validWords = validWords.concat(nextWords.words);
            if (nextWords.complete === true){
                break; //Cascade complete
            }
        }
    }
    return {
        complete:len > 0, //We broke which indicates completion
        words:validWords
    };
}

注意:" _dictionary"预计是按频率排序的单词数组。我正在使用Project Gutenberg的词汇表。