Python:按列表元素操作过滤大列表

问题描述:

我有一个大列表,我希望过滤。我想通过对列表中的每个元素执行一些操作来完成此操作,然后删除列表中的任何其他匹配元素。期望的输出是较短的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)'调用中不在列表中。 –

你的代码是因为多次调用.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循环可以在任何迭代器上工作。 –

您可以使用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

答案更简单。我们不需要枚举器。这是你在找什么? –

为什么不将列表转换为集?这确保双打已被删除。 然后延长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时它将失败。 –