Я чувствую, что ваше решение не так уж далеко от того, чтобы быть питоническим.Возможно, вы можете использовать оператор zip
, чтобы перебрать вашу строку два на два, а затем просто обнаружить локальные изменения (от пробела до буквы -> это новое слово):
string = "Hello there everyone!"
def word_index(phrase):
nb_words = 0
for a, b in zip(phrase, phrase[1:]):
if a == " " and b != " ":
nb_words += 1
yield nb_words
print(list(word_index(string)))
Здесь также используются генераторы , что довольно часто встречается в python (см. Документацию для ключевого слова yield
).Вероятно, вы можете сделать то же самое, используя itertools.accumulate
вместо цикла for, но я не уверен, что он не запутает код (см. Третий элемент из Zen of Python ).Вот как это будет выглядеть, обратите внимание, что я использовал лямбда-функцию здесь, не потому, что я думаю, что это лучший выбор, а просто потому, что я не смог найти никакого значимого имени функции:
import itertools
def word_index(phrase):
char_pairs = zip(phrase, phrase[1:])
new_words = map(lambda p: int(p[0] == " " and p[1] != " "), char_pairs)
return itertools.accumulate(new_words)
Эта втораяверсия, аналогичная первой, возвращает итератор .Обратите внимание, что использование итераторов, как правило, является хорошей идеей, поскольку в нем не делается никаких предположений о том, хочет ли ваш пользователь что-либо создавать.Если пользователь хочет преобразовать итератор it
в список, он всегда может вызвать list(it)
, как я делал в первом фрагменте кода.Итераторы просто выдают вам значения одно за другим: в любой момент времени в памяти присутствует только одно значение:
for word_index in word_index(string):
print(word_index)
Обратите внимание, что phrase[1:]
делает копию изфраза, которая означает, что это удваивает используемую память.Это можно улучшить, используя itertools.islice
, который возвращает итератор (и, следовательно, использует только постоянную память).Например, вторая версия будет выглядеть так:
def word_index(phrase):
char_pairs = zip(phrase, itertools.islice(phrase, 1, None))
new_words = map(lambda p: int(p[0] == " " and p[1] != " "), char_pairs)
return itertools.accumulate(new_words)