通过将单词与英语单词的白名单进行比较来检查单词是否为英语的快速方法?

时间:2018-10-24 08:46:16

标签: python python-3.x nltk

我正在尝试从许多(100k)预先处理的文本文件中删除所有非英语单词(porter提取并小写,删除所有非a-z字符)。我已经并行化了该过程以加快处理速度,但是它仍然非常缓慢。有没有更有效的方法在python中做到这一点?

englishwords = list(set(nltk.corpus.words.words()))
englishwords = [x.lower() for x in list(englishwords)]
englishwords = [ps.stem(w) for w in englishwords]
# this step takes too long:
shareholderletter= ' '.join(w for w in nltk.wordpunct_tokenize(shareholderletter) if w in englishwords)

1 个答案:

答案 0 :(得分:3)

您正在检查somthing in otherthing-并且您的otherthing是一个列表。

列表非常适合存储内容,但是查找列表中的“ does x in”会花费O(n)

使用set代替,它将查找降至O(1) ,并消除了所有重复项,因此,如果您要检查的基本大小,也可以在下拉菜单中查找重复了。

如果您的设置之后没有更改,请去使用frozenset-这是不可变的。

阅读:Documentation of sets

如果您使用@DeepSpace的建议,并利用集合操作,您将获得更好的性能:

s = set( t.lower().strip() for t in ["Some","text","in","set"])

t = set("Some text in a string that holds other words as well".lower().split())

print ( s&t )  # show me all things that are in both sets (aka intersection)

输出:

set(['text', 'some', 'in'])

请参见set operations


O(n):最坏的情况:您的单词是列表中20万个单词的最后一个,然后您检查了整个列表-需要进行200k个检查。

O(1):查找时间是恒定的,无论数据结构中有多少项,检查它的时间都需要相同的时间。要获得此好处,set具有更多的优点。复杂的存储解决方案,需要更多的内存(然后是列表)才能在查询中表现出色。


编辑:最糟糕的情况是 not 在集合/列表中找不到单词:

import timeit

setupcode = """# list with some dupes
l = [str(i) for i in range(10000)] + [str(i) for i in range(10000)] + [str(i) for i in range(10000)]
# set of this list
s = set( l )
"""

print(timeit.timeit("""k = "10000" in l """,setup = setupcode, number=100))
print(timeit.timeit("""k = "10000" in s """,setup = setupcode, number=100))

0.03919574100000034    # checking 100 times if "10000" is in the list
0.00000512200000457    # checking 100 times if "10000" us in the set