Я думаю, что есть три общих подхода, которые могут помочь вам избежать повторения кода в конце цикла. Для всех трех я собираюсь использовать пример задачи, немного отличающейся от вашей собственной, - подсчет слов в строке. Вот версия "по умолчанию", которая, как и ваш код, повторяет некоторую логику в конце цикла:
from collections import Counter
def countWords0(text):
counts = Counter()
word = ""
for c in text.lower():
if c not in "abcdefghijklmnopqrstuvwxyz'-":
if word:
counts[word] += 1
word = ""
else:
word += c
if word:
counts[word] += 1 # repeated code at end of loop
return counts
Первый подход - выполнять (частично) обработку «конца подпоследовательности» после каждого символа, чтобы учет был правильным, если последовательность заканчивается сразу после этого символа. В вашем примере вы можете исключить условие «else» на своем и каждый раз запускать в нем код. (Это ответ Сергерга.)
Однако это может быть непросто для некоторых видов проверок. Для подсчета слов вам нужно добавить некоторую дополнительную логику, чтобы избежать накопления мусора из «частичных» подпоследовательностей, которые вы обрабатываете. Вот код, который это делает:
def countWords1(text):
counts = Counter()
word = ""
for c in text.lower():
if c not in "abcdefghijklmnopqrstuvwxyz'-":
word = ""
else:
if word:
counts[word] -= 1 # new extra logic
word += c
counts[word] += 1 # this line was moved from above
return counts + Counter() # more new stuff, to remove crufty zero-count items
Второй вариант - добавить контрольное значение в конец последовательности, что вызовет желаемое поведение «конца подпоследовательности». Это может быть сложно, если вам нужно избежать заражения ваших данных стражем (особенно для таких вещей, как числа). Для самой длинной задачи последовательной подпоследовательности вы можете добавить любое значение, не равное последнему элементу в последовательности. None
может быть хорошим выбором. В моем примере подсчета слов подойдет не-словесный символ (например, новая строка):
def countWords2(text):
counts = Counter()
word = ""
for c in text.lower() + "\n": # NOTE: added a sentinel to the string!
if c not in "abcdefghijklmnopqrstuvwxyz'-":
if word:
counts[word] += 1
word = ""
else:
word += c
# no need to recheck at the end, since we know we ended with a space
return counts
Третий подход - изменить структуру кода, чтобы избежать повторения последовательности, которая может неожиданно закончиться. Вы можете использовать генераторы для предварительной обработки последовательности, как и в других ответах, которые используют groupby
из itertools
. (Конечно, функции генератора, если вам придется писать их самостоятельно, могут иметь аналогичные проблемы.)
В моем примере подсчета слов я могу использовать регулярные выражения из модуля re
, чтобы найти слова:
from re import finditer
def countWords3(text):
return Counter(match.group() for match in
finditer("[\w'-]+", text.lower()))
Вывод, когда задан подходящий текст Pythonic (он одинаков для всех четырех версий countWords):
>>> text = """Well, there's egg and bacon; egg sausage and bacon;
egg and spam; egg bacon and spam; egg bacon sausage and spam;
spam bacon sausage and spam; spam egg spam spam bacon and spam;
spam sausage spam spam bacon spam tomato and spam;
spam spam spam egg and spam; spam spam spam spam spam spam
baked beans spam spam spam; or Lobster Thermidor a Crevette
with a mornay sauce served in a Provencale manner with shallots
and aubergines garnished with truffle pate, brandy and with a
fried egg on top and spam."""
>>> countWords0(text)
Counter({'spam': 28, 'and': 12, 'egg': 8, 'bacon': 7, 'sausage': 4, 'a': 4,
'with': 4, 'well': 1, 'lobster': 1, 'manner': 1, 'in': 1, 'top': 1,
'thermidor': 1, "there's": 1, 'truffle': 1, 'provencale': 1,
'sauce': 1, 'brandy': 1, 'pate': 1, 'shallots': 1, 'garnished': 1,
'tomato': 1, 'on': 1, 'baked': 1, 'aubergines': 1, 'mornay': 1,
'beans': 1, 'served': 1, 'fried': 1, 'crevette': 1, 'or': 1})
person
Blckknght
schedule
22.06.2012
if some_string:
, чтобы проверить, чтоsome_string
не пусто - person jfs   schedule 22.06.2012if not l
является избыточным.l
- плохая репутация.most_reps
можно было бы назватьmax_count
, чтобы прояснить отношение кcount
.i
- ›current
,prv
-›last
- person jfs   schedule 22.06.2012