2013-03-16 3 views
2

У меня возникают проблемы с репликацией цикла for в python.Python for loop issues

Вот мой сценарий стиля c только для аспектов цикла цикла.

for ($c=0 ; $c<size($verts); $c++) 
{ 
//// do some code here 
$verts = remove($verts[c],$verts); /// remove this item from the $verts list 
$c-=1; /// lower the index becuase an item was removed 
    for ($n=0 ; $n<size($verts); $n++) 
     { 
     if($condition) 
     $verts = remove($verts[$n],$verts); /// remove this item from the $verts list 
     $n-=1; /// lower the index becuase an item was removed 
     }   
}   

В питона там не представляется возможным вычесть индекс:

item = range(10); 
for i in item : 
del item[i] 
i-=1 # this doesn't do anything for the next interation 

Что это лучший способ, чтобы написать выше цикл с в Python?

Edit: Здесь контур работает как мне нужно в питона

count = range(len(vtx)) 
for num in count: 
if len(vtx) != 0:  
    p.append ([]); p[len(p)-1].append(vtx[0]) 
    v.append ([]); v[len(p)-1].append(vec[0])  
    a = vec[0] 
    del vtx[0]  
    del vec[0] 
    count2 = range(len(vtx)) 
    n2 = 0; 
    for num2 in count2: 
     b = vec[n2] 
     distance = math.sqrt((a[0] - b[0])**2 + (a[1]- b[1])**2 + (a[2]- b[2])**2); 
     if distance <= threshold : 
      p[len(p)-1].append (vtx[n2]) 
      v[len(p)-1].append (vec[n2]) 
      vtx.remove(vtx[n2]) 
      vec.remove(vec[n2]) 
     else: 
      n2+=1 

ответ

3

Edit: На основании вашего публикуемую алгоритма, немного очистки

p, v = [[vtx.pop(0)]],[[vec.pop(0)]] 
while len(vtx):  
    x = vtx.pop(0) 
    b = vec.pop(0) 
    a = v[ -1 ][ 0 ]  
    if threshold >= math.sqrt((a[0] - b[0])**2 + (a[1]- b[1])**2 + (a[2]- b[2])**2): 
     v[ -1 ].append(b) 
     p[ -1 ].append(x) 
    else: 
     v.append([ b ]) 
     p.append([ x ]) 

Я не уверен, что

Я не уверен, что оригинальный PHP код будет работать. Или это может быть, но только случайно и, конечно, неэффективно. Я предполагаю, что вы хотите перебирать список, удаляя элементы, соответствующие определенному значению. Кажется, вы поняли, что одна из основных проблем заключается в том, что вы изменяете самый список, который вы пытаетесь перебрать. Это очень легко в Python:

for c in verts[:]: 
    if remove_condition(c): 
     verts.remove(c) 

Здесь вы делаете копию Verts списка перебрать на [:] Каждая итерация использует с, который является ссылкой на элемент в Verts -copy-. Затем вы вызываете remove() в исходный список со значением c, который удаляет -first-instance из значения c, которое он встречает.

Очевидно, что здесь существует множество нюансов в разных ситуациях, связанных с словарями и т. Д., Но это должно вас начать.

Python учебник, как правило, хороший ресурс http://docs.python.org/2/reference/compound_stmts.html#for

+0

Спасибо за все ответы. В конце концов я закончил делать что-то не очень питоническое, потому что у меня было много проблем с индексами, и я понял, что могу немного упростить свой код. (см. обновленный вопрос с рабочим кодом). Но все ответы были полезными, и я понимаю, как сейчас работает python. – fghajhe

+0

@fghajhe Я опубликовал версию, основанную на вашем редактировании, что немного легче следовать. Не уверен, что это актуально, но ваш алгоритм зависит от порядка. Если вы переупорядочиваете пары vtx/vec, вы получите разные результаты. –

3

Один идиоматических способ реализации этого заключается в следующем:

items = [el for el in items if <condition>] 

где <condition> имеет значение верно для элементов, которые вы хочу держать.

Например, чтобы получить четные числа от 0 до 9:

items = list(range(10)) 
items = [el for el in items if el % 2 == 0] 

Основная проблема с текущим кодом является то, что for i in item не перебирать индексы, а скорее перебирает сами элементы. Хотя можно использовать индексы, он имеет тенденцию вести довольно непитонический код. Кроме того, есть сложности, связанные с модификацией списка, итерации по нему.

1

Вы, кажется, думаете, что i - это индекс в вашем коде. Это не. i - это значение из списка. Для итерации по диапазону индексов используйте for i in range(len(item)):.

Однако лучшим способом удаления элементов из списка является использование понимания списка, а не ручное повторение с помощью индекса и использование del. В списках можно создать новый список, а не модифицировать новый, но, надеюсь, они все еще применимы для вашего варианта использования.

1

Удаление элементов из списка в то время как вы перебирать это может быть очень сложно. Самый безопасный способ (наименее подверженный ошибкам) ​​заключается в том, чтобы сделать копию списка, содержащую только те элементы, которые вы хотите, или удалить те, которые вы не хотите впоследствии.

Примеры:

Использование для цикла, чтобы создать новый массив только четные номера в items. Это длительный, чем писать список понимание, но, вероятно, более читаемым для кого-то нового в Python:

items = range(10) 
new_items = [] 
for item in items: 
    if item % 2 == 0: 
     new_items.append(item) 
items = new_items 
print items 

Выход:

[0, 2, 4, 6, 8] 

Используя списковых, это можно записать в виде:

items = range(10) 
items = [item for item in items if item % 2 == 0] 

Как в стороне, встроенная функция enumerate может быть вашим другом при переходе с кода C. Вы можете написать цикл, как так:

items = ['foo', 'bar', 'spam', 'eggs'] 
for i, item in enumerate(items): 
    print i, item 

Выход:

0 foo 
1 bar 
2 spam 
3 eggs