2017-08-29 45 views
1

我嘗試刪除數據庫中比選定字符i小的所有字符。數據庫是一系列字符列表。刪除函數更改無關循環的元素(Python)

def project(database, i): 
    test = database.copy() 
    for idx,lists in enumerate(database.copy()): 
     for char in lists: 
      print(char) 
      if char <= i: 
       test[idx].remove(char) 
    return test 

a = [['A','B','D'],['A','B','C','D']] 
print(project(a, 'C')) 


Output: 
A D A C 
[['B', 'D'], ['B', 'D']] 

不知何故,代碼從不檢查'B',儘管它在列表中。沒有如果條件+刪除線(5-6行)相同的代碼執行以下操作:

Output: 
A B D A B C D 
['A', 'B', 'D'], ['A', 'B', 'C', 'D']] 

爲什麼印刷字符變化雖然不改變迭代名單?

+0

'test'不是'database'的副本。嗯,它是 - 但它是一個淺拷貝。它包含對原始內部列表的引用。您需要深層複製。 – DyZ

+0

我擔心改變我正在迭代的矩陣可能會解釋奇怪的行爲。我只是檢查沒有所有副本的代碼,它也是如此。 –

+0

請閱讀答案,其中至少有一個解釋如何製作深層複印件。 – DyZ

回答

1

調試後:

的問題是不是因爲你的if語句,這是因爲刪除更改索引。

讓MT證明:

  • 與刪除列表中第一個迭代之後將是:

    ["B", "D"] 
    

而且你的指數爲1,因爲這樣"B"會忽略。

0

您的問題與您的清單database的複製有關。

python.org docs

淺表副本構造新化合物的對象,然後(在可能的程度上)插入到其在原始找到的對象的引用。

深層副本構造一個新的複合對象,然後遞歸地向其中找到的對象中插入副本。

如果深拷貝copy.deepcopy(x)你的列表中,那麼你會得到一個獨立的對象,它是不是其他的參考,而是一個完整的副本。

+0

另請參閱[本問題](https://stackoverflow.com/questions/243836/how-到複製所有的屬性-的-一個對象到另一對象合蟒) –

0

正如在其他答案中已經提到的,你的代碼有兩個問題:一個是淺拷貝,另一個是修改正在迭代的列表。但是,你甚至不需要所有這些複雜性。你的情況,很便宜,保留了「好」的項目,而不是刪除「壞」的項目:

def project(database, i): 
    return [[item for item in lst if item >= i] for lst in database] 

print(project(a, 'C')) 
# [['D'], ['C', 'D']] 

順便說一句,在條件char <= i消除了比小於或等於i項目,不只是小於i