【问题标题】:Fast way to break a joined string of words into individual words将连接的单词串分解为单个单词的快速方法
【发布时间】:2016-12-20 11:24:16
【问题描述】:

假设我有这个字符串:

hellohowareyou

有没有一种快速的方法可以将它分成单个单词,所以最终结果是hello how are you?我可以想到几种方法,但它们会非常慢(首先我需要根据字典识别每个字母,查看哪些字母组成一个单词,并且可能会有多种组合,然后我需要确定最可能的组合等.)

【问题讨论】:

  • 嗯,这可能非常很难做到。至少在我看来是这样。也许使用nltk 模块是最好的方法。
  • 嗯,您提出的方法(可能与 NLTK)会有一些变化,但我认为没有其他解决方案,因为您要求您的程序理解句子。
  • 如果你能保证所有的词都在字典里,它可以很快完成。然而,很多时候不会有一个独特的结果。例如,您的示例可以被解析为“你好,你好”。
  • 我刚刚发布了我早期代码的改进版本。

标签: python string nlp


【解决方案1】:

这是一些执行递归蛮力搜索的代码。它将单词列表放入一个集合中,因此查找速度非常快:下面的示例在我具有 2GB RAM 的旧 2 GHz 机器上运行不到 1 秒。但是,拆分比我使用的示例更长的序列肯定会花费更长的时间,主要是因为有很多可能的组合。要清除无意义的结果,您要么需要手动完成,要么使用可以进行自然语言处理的软件。

#!/usr/bin/env python3

''' Separate words

    Use dictionary lookups to recursively split a string into separate words

    See http://stackoverflow.com/q/41241216/4014959

    Written by PM 2Ring 2016.12.21
'''

# Sowpods wordlist from http://www.3zsoftware.com/download/

fname = 'scrabble_wordlist_sowpods.txt'
allwords = set('AI')
with open(fname) as f:
    for w in f:
        allwords.add(w.strip())

def parse(data, result=None):
    if result is None:
        result = []
    if data in allwords:
        result.append(data)
        yield result[::-1]
    else:
        for i in range(1, len(data)):
            first, last = data[:i], data[i:]
            if last in allwords:
                yield from parse(first, result + [last])

# Test

data = (
    'HELLOHOWAREYOU',
    'THISEXAMPLEWORKSWELL',
    'ISTHEREAFASTWAY',
    'ONE',
    'TWOWORDS',
)

for s in data:
    print(s)
    for u in parse(s):
        print(u)
    print('')    

输出

HELLOHOWAREYOU
['HELL', 'OHO', 'WARE', 'YOU']
['HELLO', 'HO', 'WARE', 'YOU']
['HELLO', 'HOW', 'ARE', 'YOU']
['HELL', 'OH', 'OW', 'ARE', 'YOU']
['HELLO', 'HOW', 'A', 'RE', 'YOU']
['HELL', 'OH', 'OW', 'A', 'RE', 'YOU']

THISEXAMPLEWORKSWELL
['THIS', 'EXAMPLE', 'WORK', 'SWELL']
['THIS', 'EX', 'AMPLE', 'WORK', 'SWELL']
['THIS', 'EXAMPLE', 'WORKS', 'WELL']
['THIS', 'EX', 'AMPLE', 'WORKS', 'WELL']

ISTHEREAFASTWAY
['I', 'ST', 'HER', 'EA', 'FAS', 'TWAY']
['IS', 'THERE', 'A', 'FAS', 'TWAY']
['I', 'ST', 'HERE', 'A', 'FAS', 'TWAY']
['IS', 'THE', 'RE', 'A', 'FAS', 'TWAY']
['I', 'ST', 'HE', 'RE', 'A', 'FAS', 'TWAY']
['I', 'ST', 'HER', 'EA', 'FAST', 'WAY']
['IS', 'THERE', 'A', 'FAST', 'WAY']
['I', 'ST', 'HERE', 'A', 'FAST', 'WAY']
['IS', 'THE', 'RE', 'A', 'FAST', 'WAY']
['I', 'ST', 'HE', 'RE', 'A', 'FAST', 'WAY']
['I', 'ST', 'HER', 'EA', 'FA', 'ST', 'WAY']
['IS', 'THERE', 'A', 'FA', 'ST', 'WAY']
['I', 'ST', 'HERE', 'A', 'FA', 'ST', 'WAY']
['IS', 'THE', 'RE', 'A', 'FA', 'ST', 'WAY']
['I', 'ST', 'HE', 'RE', 'A', 'FA', 'ST', 'WAY']

ONE
['ONE']

TWOWORDS
['TWO', 'WORDS']

此代码是为 Python 3 编写的,但您可以通过更改使其在 Python 2 上运行

yield from parse(first, result + [last])

for seq in parse(first, result + [last]):
    yield seq

顺便说一句,我们可以按长度对输出列表进行排序,即每个列表中的单词数。这往往会将更合理的结果放在顶部附近。

for s in data:
    print(s)
    for u in sorted(parse(s), key=len):
        print(u)
    print('')

【讨论】:

    【解决方案2】:

    想法:

    取句子:

    有没有一种快速的方法可以把它分成单个单词,所以最终结果是你好,我总是能想到几个,但它们会非常慢,首先需要重新识别每个字母,看看哪些字母组成一个单词...

    一个人可以很好地把它分解成一个有意义的句子。因此,一台机器应该能够做到这一点。

    服用:

    有没有办法分开

    "Is the reafastwaytoseparate..." 应该是"Is there 一种快速的分离方式" 请注意,无论在 reafast 之后取了多少个字母……它们都不会造词。

    因此,一种可能的正确方法是遍历整个句子,找到可能最短的单词,直到后面的单词不是单词。这可以通过在延长原始单词之前取 15 个字母来近似。

    在极少数情况下,您可能需要返回前两个单词,或者在极少数情况下,需要返回 2 或 3 个单词。此外,对于较长的单词来说,15 个字母可能太少了。

    最后,如果有来自其他语言的专有名词或单词,它们将不会出现在字典中。因此,在找不到单词后,可以将下一个单词作为新的起点,并且可以标记或忽略该单词。在学习模型中,在这种情况下,应该将其添加到语料库或单词中。

    将单词拆分成词性(动词、名词等)可以加快处理速度,因为例如形容词通常后跟名词。但这可能不值得付出努力,因为可能会出现另一个形容词。在任何情况下,都必须针对语料库中的所有单词进行测试,因为这不是为了检查语法而构建的。

    【讨论】:

      【解决方案3】:

      这是一个“难”的问题,因为您需要使用一些启发式算法,而不仅仅是字典。您可以将字典变成一棵树,以便从假定的单词开头逐个字母有效地搜索它,但更难的是当您遇到不在字典中的一串字母时您要去哪里。诸如“ABS”(一种塑料)或“invac”(银行员工可能是“投资账户”的简写)或“ncie”(“nice”的拼写错误)之类的东西。

      哦,还有内在的歧义,其中缺少的空格会对后面的内容产生很大的影响。考虑“治疗师”……您需要成为人类(或几乎是人类)来分析以下上下文,以确定“the”之后是否需要空格。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-01-13
        • 2013-12-12
        • 1970-01-01
        • 1970-01-01
        • 2011-10-17
        • 2021-09-05
        • 1970-01-01
        相关资源
        最近更新 更多