enumerate не работает с for
i=[]
for index, value in list(enumerate('pyjspy')):
if value =='py':
i.append(index)
print(i)
Этот код должен добавлять индексы вхождения 'py' из строки 'pyjspy' в список i, после чего вывести i с помощью print .
Почему список i всегда пустой?
Ответы (3 шт):
Что делает enumerate?
Если range() позволяет получить только индексы элементов списка, то enumerate() – сразу индекс элемента и его значение.
Таким образом list(enumerate('pyjspy')) будет выводить каждый символ из строки и его индекс:
for index, value in list(enumerate('pyjspy')):
print(index, value)
Выводит
0 p
1 y
2 j
3 s
4 p
5 y
Также во всём этом можно убедиться, если посмотреть на значение list(enumerate('pyjspy')):
print(list(enumerate('pyjspy')))
Выводит:
[(0, 'p'), (1, 'y'), (2, 'j'), (3, 's'), (4, 'p'), (5, 'y')]
Как питон итерируется по строкам?
Всё это происходит от того, как питон итерирует строки:
for i in 'pyjspy':
print(i)
Выводит:
p
y
j
s
p
y
Вывод
В итоге, i всегда оказывается пустым, т.к. value всегда принимает значение одного символа, соответственно, при сравнении value с 'py' условие никогда не будет выполняться, вследствие ничего не добавляя в i.
Нахождение подстроки в строке
Регулярные выражения
Наиболее краткий способ - использовать регулярных выражений, из встроенного модуля re:
from re import finditer
i = []
for match in finditer('py', 'pyjspy'):
i.append(match.start())
print(i)
Выведет:
[0, 4]
В данном случае finditer находит все совпадения вашей подстроки в строке, и выдаёт их вам, единственное, что осталось сделать - записать их в i.
Минус: пересекающиеся строки не будут захвачены:
Например, если вы попытаетесь найти 'aba' в 'ababa', то получите только 0
Находить с помощью str.rfind
Можно находить подстроку с помощью встроенного метода строки - rfind
Он выдаёт индекс последнего вхождения подстроки и -1, если подстрока не найдена, также можно ограничивать, где будет происходить поиск - первый и последний индекс.
s = 'pyjspy'
i = []
last_index = len(s)
while True:
last_index = s.rfind('py', 0, last_index)
if last_index == -1:
break
i.append(last_index)
print(i)
Выводит:
[4, 0]
Индексы в списке будут в порядке убывания. Данный способ тоже не будет находить пересекающиеся строки, но его можно изменить, чтобы он проходился по каждому индексу, таким образом, захватывая и пересекающиеся строки.
Находить с помощью str.find
Как с str.rfind, только находит первое вхождение.
i = []
sub = 'py'
s = 'pyjspy'
last_index = 0
while True:
last_index = s.find(sub, last_index)
if last_index == -1:
break
i.append(last_index)
last_index += len(sub)
print(i)
Выводит:
[0, 4]
Этот способ тоже не захватывает пересекающиеся подстроки, и его тоже можно изменить, чтобы захватвал.
Находить с помощью срезов
В данном случае мы будем использовать срезы [<начальный индекс>:<конечный индекс + 1>], т.е. 'abcd'[0:2] == 'ab'
s = 'pyjspy'
i = []
for index in range(len(s)):
if s[index:index+2] == 'py':
i.append(index)
print(i)
Выводит:
[0, 4]
Этот способ будет чуть медленнее, т.к. перебирает каждую пару ближних символов, зато справится с нахождением пересекающихся подстрок.
Дополнительная информация
Итерация - это общий термин для взятия каждого элемента чего-либо, одного за другим. Каждый раз, когда вы используете цикл, явный или неявный, чтобы пройти через группу элементов, это итерация.
Список пустой потому, что ваша строка будет разбита на буквы, и value =='py' никогда не сработает.
Для поиска подстрок можно самому итерироваться по подстрокам. Ну или через регексп.
text = 'pyjspy'
search = 'py'
i=[]
for index in range(len(text)-len(search)+1):
if text[index:index+len(search)] == search:
i.append(index)
print(i)
# альтернативный метод
import re
x = [m.start() for m in re.finditer(search, text)]
print(x)
как вариант
text = 'pyjspy'
list_i = []
for index, value in enumerate(text):
if text[index:index+2] =='py':
list_i.append(index)
print(list_i)