Итерация через слово String за раз в Python

У меня есть строковый буфер огромного текстового файла. Я должен искать определенные слова / фразы в буфере строк. Каков эффективный способ сделать это?

Я пробовал использовать 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() 

8 Solutions collect form web for “Итерация через слово String за раз в Python”

Итерация по слову через содержимое файла (Волшебник из страны Оз из проекта Гутенберг, в моем случае), три разных способа:

 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 

Это похоже на проблему, в которой trie действительно поможет. Вы, вероятно, должны использовать какой-то сжатый трю, как Patricia / radix trie . Пока вы можете вместить весь словарь слов / фраз, который вы ищете в trie, это значительно сократит сложность времени. Как это будет работать, вы берете начало слова и опускаете три, пока не найдете самое длинное совпадение и не увеличите счетчик в этом узле. Это может означать, что вам нужно подняться на три, если частичное совпадение не закончится. Затем вы переходите к началу следующего слова и делаете это снова. Преимущество trie заключается в том, что вы просматриваете весь словарь с каждым поиском через trie (каждый поиск должен занимать O (m), где m – средняя длина слова / фразы в вашем словаре).

Если вы не можете вместить весь словарь в один трюк, вы можете разбить словарь на несколько попыток (один для всех слов / фраз, начинающихся с al, один для mz, например) и выполнить развертку по всему корпусу для каждого Trie.

Если модуль re не сможет сделать это быстро, вам будет трудно сделать это быстрее. В любом случае вам нужно прочитать весь файл. Вы можете подумать об исправлении своего регулярного выражения (можете ли вы предоставить его?). Возможно, некоторый опыт того, что вы пытаетесь достичь.

Вы можете попробовать сделать это наоборот … вместо обработки текстового корпуса 2 000 000 раз (один раз для каждого слова), обрабатывайте его только один раз. Для каждого слова в корпусе, увеличивайте хэш-таблицу или аналогично, чтобы сохранить количество этого слова. Простой пример в псевдокоде:

 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_counts с полным списком слов, это не нужно, если оператор … не уверен.

Как сказал xyld, я не думаю, что вы можете побить скорость модуля re, хотя это поможет, если вы разместите свои регулярные выражения и, возможно, код. Все, что я могу добавить, это профилирование перед оптимизацией. Вы можете быть очень удивлены, когда увидите, где проходит большая часть обработки. Я использую hotshot для профайла моего кода и вполне доволен этим. Вы можете найти хорошее введение в профилирование python здесь http://onlamp.com/pub/a/python/2005/12/15/profiling.html .

Если вы используете re не достаточно хорошо, вы, вероятно, используете findall() или вручную findall() совпадения. Использование итератора может сделать это быстрее:

 >>> for i in re.finditer(r'\w+', 'Hello, this is a sentence.'): ... print i.group(0) ... Hello this is a sentence 
 #!/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 

Но каждая «фраза», явно добавленная в регулярное выражение, скажется на производительности – выше на 50% медленнее, чем просто «\ w +», по моим грубым измерениям.

Рассматривали ли вы просмотр набора инструментов Natural Language Toolkit . Он включает в себя множество приятных функций для работы с текстовым корпусом, а также класс класс FreqDist, который ведет себя как диктофон (имеет ключи) и list-like (slice).

  • TypeError: недостаточно аргументов для строки формата при использовании% s
  • Как разбирать произвольную строку параметров в словаре python
  • сравнение двух строк с «is» - не выполняется, как ожидалось
  • Расположение класса строки python в исходном коде
  • Самая длинная общая подстрока из более чем двух строк - Python
  • Как получить объект из строки?
  • Насколько медленным является конкатенация строк Python и str.join?
  • python подсчет букв в строке без функции count
  • Python - лучший язык программирования в мире.