Python 在单词列表中搜索一组单词的快速方法

Python 在单词列表中搜索一组单词的快速方法,python,string,search,nltk,Python,String,Search,Nltk,我有一套大小为20的固定单词。我有一个20000条记录的大文件,其中每条记录都包含一个字符串,我想知道是否有固定集合中的任何单词存在于字符串中,以及是否存在该单词的索引 范例 s1=set([barely,rarely, hardly])#( actual size 20) l2= =["i hardly visit", "i do not visit", "i can barely talk"] #( actual size 20,000) def get_token_index(tok

我有一套大小为20的固定单词。我有一个20000条记录的大文件,其中每条记录都包含一个字符串,我想知道是否有固定集合中的任何单词存在于字符串中,以及是否存在该单词的索引

范例

s1=set([barely,rarely, hardly])#( actual size 20) 

l2= =["i hardly visit", "i do not visit", "i can barely talk"] #( actual size 20,000)

def get_token_index(token,indx):
    if token in s1:
        return indx
    else:
        return -1


def find_word(text):
    tokens=nltk.word_tokenize(text)
    indexlist=[]
    for i in range(0,len(tokens)):
        indexlist.append(i)
    word_indx=map(get_token_index,tokens,indexlist)    
    for indx in word_indx:
        if indx !=-1:
           # Do Something with tokens[indx]

我想知道是否有更好/更快的方法

您可以将列表理解与双for循环一起使用:

s1=set(["barely","rarely", "hardly"])

l2 = ["i hardly visit", "i do not visit", "i can barely talk"]

locations = [c for c, b in enumerate(l2) for a in s1 if a in b]
在本例中,输出为:

[0, 2]
但是,如果您想要访问某个单词出现的索引的方式:

from collections import defaultdict

d = defaultdict(list)

for word in s1:
   for index, sentence in l2:
       if word in sentence:
           d[word].append(index)

您可以将列表理解与双for循环一起使用:

s1=set(["barely","rarely", "hardly"])

l2 = ["i hardly visit", "i do not visit", "i can barely talk"]

locations = [c for c, b in enumerate(l2) for a in s1 if a in b]
在本例中,输出为:

[0, 2]
但是,如果您想要访问某个单词出现的索引的方式:

from collections import defaultdict

d = defaultdict(list)

for word in s1:
   for index, sentence in l2:
       if word in sentence:
           d[word].append(index)

这只会消除一些明显的低效率,但不会影响解决方案的总体复杂性:

def find_word(text, s1=s1): # micro-optimization, make s1 local
    tokens = nltk.word_tokenize(text)    
    for i, word in in enumerate(tokens):
        if word in s1:
           # Do something with `word` and `i`

本质上,当您真正需要的只是循环体内部的一个条件时,使用
map
会减慢速度。。。因此,基本上,只要去掉
get\u token\u index
,它就被过度设计了。

这只会消除一些明显的低效,但不会影响解决方案的整体复杂性:

def find_word(text, s1=s1): # micro-optimization, make s1 local
    tokens = nltk.word_tokenize(text)    
    for i, word in in enumerate(tokens):
        if word in s1:
           # Do something with `word` and `i`
本质上,当您真正需要的只是循环体内部的一个条件时,使用
map
会减慢速度。。。因此,基本上,只要去掉
get\u token\u index
,它就被过度设计了。

这应该可以:

strings = []
for string in l2:
    words = string.split(' ')
    for s in s1:
        if s in words:
            print "%s at index %d" % (s, words.index(s))
这应该起作用:

strings = []
for string in l2:
    words = string.split(' ')
    for s in s1:
        if s in words:
            print "%s at index %d" % (s, words.index(s))

最简单的方法和稍微更有效的方法是使用Python生成器函数

index_tuple=list((l2.index(i)表示s1中的i,l2中的i))


您可以对它计时,并检查它与您的需求配合的效率

最简单的方法是使用Python生成器函数,效率稍高一些

index_tuple=list((l2.index(i)表示s1中的i,l2中的i))


您可以对其计时并检查其与您的需求的有效性

您不需要对文本调用标记化吗?对于初学者,绝对不需要预先构建索引列表,使用
枚举
迭代您的项/索引。当然,这只会减少常量因素……您不需要对文本调用tokenize吗?对于初学者来说,绝对不需要预先构建索引列表,使用
枚举
迭代项目/索引。当然,这只会减少常量因子…这会更慢,因为它不检查单个令牌是否在集合中,而是在集合上迭代(红色标记!),并检查集合元素是否在字符串中…这会更慢,因为它不检查单个令牌是否在集合中,而是在集合上迭代(红旗!)并检查集合元素是否在字符串中…这将较慢,因为它在集合中迭代,而不是检查集合中的成员身份(使用集合的整个点…),这将较慢,因为它在集合中迭代,而不是检查集合中的成员身份(使用集合的整个点…)我认为map应该更快,因为它可以在列表上进行并行搜索。@AMisra“并行搜索”是什么意思?内置的
映射不可用concurrent@AMisra无论如何,这不是最大的问题,最大的问题是不需要预先建立索引列表,这是低效的。这就是为什么
range
enumerate
存在的原因。你的
map
ing没有任何用处,只是增加了一层额外的功能调用。我认为map将执行并行执行,因此我尝试添加它。有没有方法执行并行执行?我看到了带池函数的多处理库,但它谈到了主检查。@在CPython中,您必须使用
多处理
,注意,它本质上是
子进程
的包装器,并且这不是小事。我认为map应该更快,因为它可以在列表上进行并行搜索。@AMisra“并行搜索”是什么意思?内置的
映射不可用concurrent@AMisra无论如何,这不是最大的问题,最大的问题是不需要预先建立索引列表,这是低效的。这就是为什么
range
enumerate
存在的原因。你的
map
ing没有任何用处,只是增加了一层额外的功能调用。我认为map将执行并行执行,因此我尝试添加它。有没有方法执行并行执行?我看到了带池函数的多处理库,但它谈到了主检查。@在CPython中,您必须使用
多处理
,注意,它本质上是
子进程
的包装器,并且这不是小事。