В си-подобных языках предоставляется возможность определить изменение переменной в объявлении for
, а далее в самом цикле изменять её значение. Пример на С++11:
std::vector<int> a = {1,2,3,3,3,4,5};
auto next=a.begin(); next++;
for(auto i=a.begin();i!=a.end();i++, next++){
while (next != a.end() && *i == *next) {
i++;
next++;
}
std::cout << *i<<std::endl;
}
Как можно реализовать такое же перемещение по элементам tuple, string etc
в Python?
Так как единственное, что приходит в голову :
a = "Python is cool"
prev = ""
for elem in a:
if elem == prev:
continue
print(elem)
prev = elem
Чтобы убрать подряд идущие дубликаты, можно itertools.groupby()
использовать:
from itertools import groupby
def uniq_adjacent(iterable):
return (first for first, same_adjacent_items in groupby(iterable))
Пример:
>>> numbers = 1, 2, 3, 3, 3, 4, 5
>>> print(*uniq_adjacent(numbers))
1 2 3 4 5
Остались только первые вхождения из повторяющихся элементов, которые рядом находятся. Обычно это пишется как:
from operator import itemgetter
def uniq_adjacent(iterable):
return map(itemgetter(0), groupby(iterable))
Результат тот же. См. ещё unique_justseen()
itertools' рецепт, чтобы поддерживать произвольный ключ для сравнения.
Чтобы руками такое реализовать:
def uniq_adjacent(iterable):
last = object()
for item in iterable:
if item != last:
yield item
last = item
Использование абсолютно такое как и у предыдущих вариантов. Обратите внимание, индекс нигде явно не используется. Этот вариант аналогичен Питон-коду из вопроса (работает и для tuple, strings, etc).
Если хочется реализовать без использования for
-цикла:
class uniq_adjacent:
def __init__(self, iterable):
self.it = iter(iterable)
self.last = self.current = object()
def __iter__(self):
return self
def __next__(self):
while self.last == self.current:
self.current = next(self.it) # exit on StopIteration
self.last = self.current
return self.current
Работает также. Аналогом *next++
из C++ здесь является next(iterator)
.
Вот совершенно неидиоматичный Питон-код, который старается построчно близко форму C++ кода повторить, чтобы показать что возможно for-цикл и next()
совместить для одно и того же итератора (здесь и как правило это плохая идея):
from itertools import tee, zip_longest
def uniq_adjacent_do_not_use(iterable, sentinel=object()):
# XXX DO NOT USE
a, b = tee(iterable)
next(b, None)
for x, y in zip_longest(a, b, fillvalue=sentinel): # iterate pairwise
while x == y:
x = next(a)
y = next(b, sentinel)
yield x
Для проверки, посмотрите сможете ли вы понять как работает решение, использующее tee(), zip(), next() в Формирование вложенных в список списков из других списков по определенным правилам?
Изменение переменной, которая определяет условие работы цикла внутри тела цикла - плохой стиль программирования.
Python, который позиционирует себя как "язык для чистого и красивого программирования", не может разрешить вам делать такие вещи легко. Python не дает такого же контроля над циклом for
, как это делают другие языки.
Вообще, for
предназначен исключительно для итерирования над итерируемыми структурами данных (список, генератор, etc.).
В данном случае, вам придется использовать цикл while
.
Так можно:
it = iter(range(0, 10))
for elem in it:
print('for[0]: ', elem)
if elem == 1:
for elem1 in it:
print('for[1]: ', elem1)
if elem1 == 6:
break
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Нужно ли использовать css хаки в 2017 году? Например для border-rarius, border-box, box-shadow и так далее