2016-03-01 65 views
-1

我有一個大列表,我希望過濾。我想通過對列表中的每個元素執行一些操作來完成此操作,然後刪除列表中的任何其他匹配元素。期望的輸出是較短的ls,刪除了匹配的後期操作元素。我可以做到這一點,但它真的很慢。 你有什麼建議可以加快速度嗎?Python:按列表元素操作過濾大列表

一個例子列表如下所示:

ls = [1,2,3,......,10000000] 

和操作是這樣的:

def performOps(x): 
    a = x**2 
    b = x**5 
    c = x**7 
    return a,b,c 

for elem in ls: 
    res = performOps(elem) 
    for i in res: 
     if i in ls[ls.index(elem)+1:]: 
      ls.remove(elem) 
+0

你的代碼不起作用 - 它給了我'ValueError: 2在'ls.index(elem)'調用中不在列表中。 –

回答

1

你的代碼是因爲多次調用.index緩慢。另外,編輯列表的同時也在迭代它,這在技術上是可行的,但很難調試。

下面是我們首先構建一組要刪除的數字,然後使用單個filter調用刪除它們的方法。這組數字是一個集合,因爲對於大數目組來說,測試集合中的成員比列表中要快得多:

# Make a set a numbers that we need to remove 
toRemove = set() 
for elem in ls: 
    res = performOps(elem) 
    for i in res: 
     toRemove.add(i) 
# Remove those numbers 
ls = list(filter(lambda x: x not in toRemove, ls)) 
+0

我很喜歡這個解決方案:) 但唯一的問題是performOps返回一個列表,所以我需要附加到remove。 – user70434

+0

@ user70434如果performOps返回一個列表,這個代碼將工作,因爲for循環可以在任何迭代器上工作。 –

1

您可以使用enumerate()

# Iterate list along with index as 'i' 
for elem in list(ls): 
    res = performOps(elem) 
    if i in ls: 
     ls.remove(x) 

使用list(ls)遍歷列表阻止索引問題的副本,由於內環路列表的修改。

+0

我正在調用ls.index,因爲我正在使用ls.remove。列表長度不斷變化,所以我不想只使用i計數器作爲索引位置,因爲ls中元素的索引可能會從一次迭代變爲下一次迭代。 – user70434

+0

更新了我的答案。我正在使用'enumerate(list(ls))'來防止列表的索引。 'list(ls)'將創建'ls'的副本。這種迭代將在另一個列表中,並且索引將被阻止。還刪除了'如果我在ls [i + 1:]'條件。 –

+0

答案更簡單。我們不需要枚舉器。這是你在找什麼? –

0

爲什麼不將列表轉換爲集?這確保雙打已被刪除。 然後延長Moinuddin誇德里的回答

def filter(ls): 
    final_list = set() 
    for index, elem in enumerate(ls): 
    final_list.add(elem) 
    for item in performOps(elem): 
     if item in ls: 
     ls.remove(item) 
    return final_list 

ls = set([1,2,3.....10000]) 
ls = filter(ls) 
+0

你爲什麼要把'ls'轉換成'set()'? 'ls'可能有重複的值。 –

+0

是否需要重複值?原代碼在我看來像重複是不需要的。如果是這樣,我們可以在運行performOps方法之前轉換爲集合並過濾重複項,從而節省循環時間。 –

+0

此代碼有一個錯誤:在嘗試刪除它之前,您需要檢查元素是否在集合中。對於perfomOps(1),它返回(1,1,1),並且在第二次嘗試刪除1時它將失敗。 –