2013-03-31 2 views
4

Я повторяю список. Элемент может быть добавлен в этот список во время итерации. Таким образом, проблема в том, что цикл повторяется только через исходную длину этого списка.Как создать цикл for с динамическим диапазоном?

Мой код:

i = 1 
    for p in srcPts[1:]: # skip the first item. 
     pt1 = srcPts[i - 1]["Point"] 
     pt2 = p["Point"] 

     d = MathUtils.distance(pt1, pt2) 
     if (D + d) >= I: 
      qx = pt1.X + ((I - D)/d) * (pt2.X - pt1.X) 
      qy = pt1.Y + ((I - D)/d) * (pt2.Y - pt1.Y) 
      q = Point(float(qx), float(qy)) 
      # Append new point q. 
      dstPts.append(q) 
      # Insert 'q' at position i in points s.t. 'q' will be the next i. 
      srcPts.insert(i, {"Point": q}) 
      D = 0.0 
     else: 
      D += d 
     i += 1 

Я попытался с помощью for i in range(1, len(srcPts)): но опять диапазон остается неизменным даже после того, как другие элементы, которые были добавлены в список.

ответ

4

Проблема заключается в том, что len(srcPts) вычисляется только один раз, когда вы передаете его в качестве аргумента генератору range. Поэтому вам нужно иметь условие завершения, которое повторно оценивает текущую длину srcPts во время каждой итерации. Там же много способов сделать это, такие как:

while i < len(srcPts): 


    .... 
+0

Спасибо, я такой нуб Python. –

8

Вы должны использовать while петли вместо этого в этом случае:

i = 1 
while i < len(srcPts): 
    # ... 
    i += 1 

for цикла создает итератор для списка, раз. И однажды созданный этот итератор не знает, что вы изменили список в цикле. Вариант while, показанный здесь , пересчитывает длину каждый раз вместо этого.

+0

Ну, это неправда. Python позволяет вам изменять список, который вы выполняете. Фактически, когда вы добавляете в список, он сканирует этот добавленный элемент; то же самое для вставки элементов. Чтобы сделать копию вашего списка для итерации по ней, вы можете написать 'for i в lst [:]:' или делать другие трюки. Подробнее об этом [здесь] (http://docs.python.org/2/tutorial/controlflow.html#for-statements). –

+0

@SergeyIvanov: Я не сказал, что Python не позволяет вам, я сказал, что цикл 'for' не знает, что список был изменен. Обратите внимание, что OP * уже использовал срез * здесь. Он перебирает частичную копию (все, кроме 1-го элемента). –

+0

@ Сергий Иванов: И в этом суть; OP * хочет, чтобы цикл включал добавленные элементы *, вставленные в тело цикла. –

1

В строке:

for p in srcPts[1:]: # skip the first item. 

нарезка делает новую копию scrPtrs, поэтому фиксированный размер.

Отказ от ответственности: Это чувствует себя неправильно, чтобы изменить список будучи итератор, но это работает ...

Создать итератор список предотвращает копию и все еще позволяет элементы, которые будут добавлены и вставлены:

L = [1,2,2,3,4,5,2,2,6] 
it = iter(L) 
next(it) # skip the first item 
for i,p in enumerate(it,1): 
    if p == 2: 
     L.insert(i+1,7) # insert a 7 as the next item after each 2 
    print(p) 

Выход:

2 
7 
2 
7 
3 
4 
5 
2 
7 
2 
7 
6