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)
你的代码是因为多次调用.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))
我很喜欢这个解决方案:) 但唯一的问题是performOps返回一个列表,所以我需要附加到remove。 – user70434
@ 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)
遍历列表阻止索引问题的副本,由于内环路列表的修改。
我正在调用ls.index,因为我正在使用ls.remove。列表长度不断变化,所以我不想只使用i计数器作为索引位置,因为ls中元素的索引可能会从一次迭代变为下一次迭代。 – user70434
更新了我的答案。我正在使用'enumerate(list(ls))'来防止列表的索引。 'list(ls)'将创建'ls'的副本。这种迭代将在另一个列表中,并且索引将被阻止。还删除了'如果我在ls [i + 1:]'条件。 –
答案更简单。我们不需要枚举器。这是你在找什么? –
为什么不将列表转换为集?这确保双打已被删除。 然后延长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)
你为什么要把'ls'转换成'set()'? 'ls'可能有重复的值。 –
是否需要重复值?原代码在我看来像重复是不需要的。如果是这样,我们可以在运行performOps方法之前转换为集合并过滤重复项,从而节省循环时间。 –
此代码有一个错误:在尝试删除它之前,您需要检查元素是否在集合中。对于perfomOps(1),它返回(1,1,1),并且在第二次尝试删除1时它将失败。 –
你的代码不起作用 - 它给了我'ValueError: 2在'ls.index(elem)'调用中不在列表中。 –