在Python中一次遍历字符串单词

在Python中一次遍历字符串单词,python,string,string-matching,Python,String,String Matching,我有一个巨大文本文件的字符串缓冲区。我必须在字符串缓冲区中搜索给定的单词/短语。做这件事的有效方法是什么 我试着使用re模块匹配。但由于我有一个庞大的文本语料库,我必须搜索。这需要花费大量的时间 给你一本单词和短语词典 我遍历每个文件,将其读入字符串,搜索字典中的所有单词和短语,如果找到键,则增加字典中的计数 我们认为的一个小优化是对短语/单词字典进行排序,将最大单词数降到最低。然后比较字符串缓冲区中每个单词的起始位置,并比较单词列表。如果找到一个短语,我们不会搜索其他短语(因为它匹配的是最长的

我有一个巨大文本文件的字符串缓冲区。我必须在字符串缓冲区中搜索给定的单词/短语。做这件事的有效方法是什么

我试着使用re模块匹配。但由于我有一个庞大的文本语料库,我必须搜索。这需要花费大量的时间

给你一本单词和短语词典

我遍历每个文件,将其读入字符串,搜索字典中的所有单词和短语,如果找到键,则增加字典中的计数

我们认为的一个小优化是对短语/单词字典进行排序,将最大单词数降到最低。然后比较字符串缓冲区中每个单词的起始位置,并比较单词列表。如果找到一个短语,我们不会搜索其他短语(因为它匹配的是最长的短语,这正是我们想要的)

有人能建议如何在字符串缓冲区中逐字进行吗。(逐字迭代字符串缓冲区)

此外,是否有其他优化,可以在这方面做

data = str(file_content)
for j in dictionary_entity.keys():
    cnt = data.count(j+" ")
    if cnt != -1:
        dictionary_entity[j] = dictionary_entity[j] + cnt
f.close()

如果
re
模块不能快速完成,您将很难再快速完成。无论哪种方式,您都需要读取整个文件。你可以考虑修复正则表达式(你能提供一个表达式吗?)也许你还需要了解一些你想要完成的事情的背景。

你可以试着用另一种方式来完成……不要对文本语料库进行2000000次处理(每个单词一次),只处理一次。对于语料库中的每个单词,增加一个哈希表或类似的值来存储该单词的计数。伪代码中的一个简单示例:

word_counts = new hash<string,int>
for each word in corpus:
  if exists(word_counts[word]):
    word_counts[word]++
  else:
    word_counts[word] = 1
word\u counts=新哈希
对于语料库中的每个单词:
如果存在(字数[字数]):
字数++
其他:
字数[字数]=1

你也许可以通过提前初始化单词的完整列表来加速它,这不需要if语句…不确定。

正如xyld所说,我认为你不能超过re模块的速度,尽管如果你发布你的正则表达式和可能的代码也会有所帮助。我所能做的就是在优化之前尝试分析。当您看到大部分处理都在哪里时,您可能会非常惊讶。我使用hotshot来分析我的代码,我对此非常满意。您可以在这里找到一个很好的python评测介绍。

如果使用
re
的性能不够,您可能使用
findall()
,或者手动逐个查找匹配项。使用迭代器可能会加快速度:

>>> for i in re.finditer(r'\w+', 'Hello, this is a sentence.'):
...     print i.group(0)
...     
Hello
this
is
a
sentence

这听起来像是一个真正有帮助的问题。您可能应该使用某种压缩的trie,比如。只要你能在trie中找到你正在寻找的单词/短语的整个字典,这将大大降低时间复杂度。它的工作原理是取一个单词的开头,然后下降trie,直到找到最长的匹配项,并增加该节点中的计数器。这可能意味着,如果部分匹配不成功,您必须提升trie。然后你会继续下一个单词的开头,然后再做一次。trie的优点是,每次通过trie进行搜索时,您都在搜索整个词典(每次查找大约需要O(m),其中m是词典中单词/短语的平均长度)

如果不能将整个词典放入一个trie中,那么可以将词典拆分为几次尝试(一次用于所有以a-l开头的单词/短语,一次用于m-z),并对每个trie扫描整个语料库

#!/usr/bin/env python
import re

s = ''
for i in xrange(0, 100000):
    s = s + 'Hello, this is a sentence. '
    if i == 50000:
        s = s + " my phrase "

s = s + 'AARRGH'

print len(s)

itr = re.compile(r'(my phrase)|(\w+)').finditer(s)
for w in itr:
    if w.group(0) == 'AARRGH':
        print 'Found AARRGH'
    elif w.group(0) == "my phrase":
        print 'Found "my phrase"'
运行这个,我们得到

$ time python itrword.py
2700017
Found "my phrase"
Found AARRGH

real    0m0.616s
user    0m0.573s
sys     0m0.033s

但是,明确添加到正则表达式中的每一个“短语”都会对性能产生影响——根据我的粗略测量,上述操作比仅使用“\w+”慢50%。

以三种不同的方式逐字迭代文件内容(在我的例子中,是古腾堡项目的Oz向导):

from __future__ import with_statement
import time
import re
from cStringIO import StringIO

def word_iter_std(filename):
    start = time.time()
    with open(filename) as f:
        for line in f:
            for word in line.split():
                yield word
    print 'iter_std took %0.6f seconds' % (time.time() - start)

def word_iter_re(filename):
    start = time.time()
    with open(filename) as f:
        txt = f.read()
    for word in re.finditer('\w+', txt):
        yield word
    print 'iter_re took %0.6f seconds' % (time.time() - start)

def word_iter_stringio(filename):
    start = time.time()
    with open(filename) as f:
        io = StringIO(f.read())
    for line in io:
        for word in line.split():
            yield word
    print 'iter_io took %0.6f seconds' % (time.time() - start)

woo = '/tmp/woo.txt'

for word in word_iter_std(woo): pass
for word in word_iter_re(woo): pass
for word in word_iter_stringio(woo): pass
导致:

% python /tmp/junk.py
iter_std took 0.016321 seconds
iter_re took 0.028345 seconds
iter_io took 0.016230 seconds

你有没有考虑过看报纸。它包括许多用于处理文本语料库的好函数,还有一个很酷的FreqDist类,它的行为类似于dict(有键)和list(切片)

我有一个巨大的文本语料库,我正在尝试获取这个语料库中200万个短语/单词的出现次数。你是在实现一个单词/短语计数器还是什么?是的,实现了一个单词/短语计数器。语料库是我搜索的字符串缓冲区。有数百万个文件,我必须从中获得单词/短语的所有出现次数(这是预定义的),因此如果我的哈希单词/短语列表中有“黄金之城”、“城市”和“黄金”。如果有“这是黄金之城”的话。那么我的计数器应该只为“黄金之城”增加。但是哈希中的字符串可能是多个单词。因此,与每个单词相比,我可以算出“城市”和“黄金”,但不能算出“黄金之城”@AlgoMan,你没有理由不能对每个单词或短语都算数,并把它们都写在字典里。@mikerobi我可以把这些短语放进字典里。但语料库是逐字搜索的,而不是逐句搜索的。我如何在语料库中搜索词组,并在单词上递增,然后再搜索词组。我有单词列表,50MB的文件。我需要搜索200万个单词/短语。我刚刚使用一个非常简单的patricia trie实现对200万个随机生成的平均长度为22.5个字母的短语进行了测试,这是我不久前提出的,在我的机器上花费了684 MB。我还将随机生成的短语保存到一个文本文件中,该文件为48MB。这似乎还不算太糟糕,尤其是考虑到我的实现的内存效率不是很高。但是如果我想搜索一个短语呢?如果w.group(0)=‘这是一个’:print“找到‘这是一个’”“我该怎么做?”@AlgoMan:我想中心问题是,‘有人能建议如何在字符串缓冲区中逐字进行吗?’。(按字迭代字符串缓冲区。)