2013-03-16 163 views
2

我遇到了在python中複製for循環的問題。Python for循環問題

這是我的c風格的腳本,只有for循環方面。

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語言編寫上面的C循環的最佳方式?

編輯: 這裏是循環的工作,因爲我需要在Python

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

編輯:根據您發佈的算法,一點點清理

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) 

在這裏,你正在綠黨的副本中列出了遍歷[:] 每次迭代使用C,這是在綠黨-copy-到項目的引用。 然後,您使用值c調用原始列表上的remove(),該值將刪除它遇到的值c的-first-實例。

很明顯,在涉及字典等不同情況下,這裏有很多細微差別,但這應該讓你開始。

Python的教程通常是一個很好的資源http://docs.python.org/2/reference/compound_stmts.html#for

+0

感謝所有的答案。我最終做了一些不太pythonic的事情,因爲我仍然對索引有很多麻煩,並且意識到我可以簡化我的c代碼。 (請參閱帶有工作代碼的更新問題)但是所有的答案都很有幫助,現在我明白了python的工作原理。 – fghajhe 2013-03-16 19:40:46

+0

@fghajhe我發佈了一個基於你的編輯的版本,這個版本更容易遵循。不確定它是否相關,但你的算法是依賴於順序的。如果你重新排列你的vtx/vec對,你會得到不同的結果。 – 2013-03-17 00:03:49

3

一種慣用的方式來實現,這是如下:

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

其中<condition>計算結果爲true的元素,你想保持

例如,爲了獲得偶數0到9之間:

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

與您現有的代碼的主要問題是,for i in item不隨指數迭代,但在內容本身,而迭代。儘管可以使用索引,但它往往會導致相當的非Pythonic代碼。此外,在迭代它的同時修改列表還有一些複雜性。

1

您似乎認爲i是您的代碼中的索引。不是。 i是來自列表的值。要遍歷一系列索引,請使用for i in range(len(item)):

但是,從列表中刪除項目的更好方法是使用列表理解,而不是手動迭代索引並使用del。列表解析將創建一個新列表,而不是修改一個新列表,但希望它們仍適用於您的用例。

1

從列表中刪除項目,而你遍歷它可以是非常棘手的。最安全(最不容易出錯)的方式是製作一個列表的副本,只包含你想要的元素或刪除之後你不想要的元素。

例子:

使用for循環中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] 

另外,從C代碼移動時,內置函數enumerate可以成爲您的朋友。你可以像這樣寫一個for循環:

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

輸出:

0 foo 
1 bar 
2 spam 
3 eggs