Я хотел бы сделать это с помощью словаря наборов для отслеживания номеров строк. На самом деле для упрощения вещей я использовал бы collections.defaultdict
со значениями, которые были типа set
. Как уже упоминалось в другом ответе, лучше всего проанализировать слова, используя регулярное выражение через модуль re
.
from collections import defaultdict
import re
# Only process words at least a minimum number of letters long.
MIN_WORD_LEN = 3
WORD_RE = re.compile('[a-zA-Z]{%s,}' % MIN_WORD_LEN)
def make_index(input_file):
index = defaultdict(set)
for line_num, line in enumerate(input_file, start=1):
for word in re.findall(WORD_RE, line.lower()):
index[word].add(line_num) # Make sure line number is in word's set.
# Convert result into a regular dictionary of simple sequence values.
return {word:tuple(line_nums) for word, line_nums in index.iteritems()}
Альтернативные не используется re
модуля:
from collections import defaultdict
import string
# Only process words at least a minimum number of letters long.
MIN_WORD_LEN = 3
def find_words(line, min_word_len=MIN_WORD_LEN):
# Remove punctuation and all whitespace characters other than spaces.
line = line.translate(None, string.punctuation + '\t\r\n')
return (word for word in line.split(' ') if len(word) >= min_word_len)
def make_index(input_file):
index = defaultdict(set)
for line_num, line in enumerate(input_file, start=1):
for word in find_words(line.lower()):
index[word].add(line_num) # Ensure line number is in word's set.
# Convert result into a regular dictionary of simple sequence values.
return {word:tuple(line_nums) for word, line_nums in index.iteritems()}
В любом случае, функция make_index()
может быть использована и вывод результатов в двух столбцах, как это:
with open('StoryTime.txt', 'rt') as story_file:
index = make_index(story_file)
longest_word = max((len(word) for word in index))
for word, line_nums in sorted(index.iteritems()):
print '{:<{}} {}'.format(word, longest_word, line_nums)
В качестве тестового примера Я использовал следующий отрывок (обратите внимание, что слово «die» находится в последней строке дважды):
Now the serpent was more subtle than any beast of the field which
the LORD God had made. And he said unto the woman, Yea, hath God said,
Ye shall not eat of every tree of the garden? And the woman said
unto the serpent, We may eat of the fruit of the trees of the garden:
But of the fruit of the tree which is in the midst of the garden,
God hath said, Ye shall not eat of it, neither shall ye touch it, lest
ye die, or we all die.
и получить следующие результаты:
all (7,)
and (2, 3)
any (1,)
beast (1,)
but (5,)
die (7,)
eat (3, 4, 6)
every (3,)
field (1,)
fruit (4, 5)
garden (3, 4, 5)
god (2, 6)
had (2,)
hath (2, 6)
lest (6,)
lord (2,)
made (2,)
may (4,)
midst (5,)
more (1,)
neither (6,)
not (3, 6)
now (1,)
said (2, 3, 6)
serpent (1, 4)
shall (3, 6)
subtle (1,)
than (1,)
the (1, 2, 3, 4, 5)
touch (6,)
tree (3, 5)
trees (4,)
unto (2, 4)
was (1,)
which (1, 5)
woman (2, 3)
yea (2,)
Есть ли способ сделать это без импорта модуля? – Dragonchicken
Несомненно ... см. Обновление. Я также модифицировал его, поэтому индекс слова нечувствителен к регистру. – martineau
P.S. Если вы нашли мой ответ полезным, подумайте об этом: [_Что делать, когда кто-то отвечает на мой вопрос? _] (Http://stackoverflow.com/help/someone-answers) – martineau