【问题标题】:Python: Filtering large list by operations on list elementsPython:通过对列表元素的操作过滤大列表
【发布时间】:2016-03-01 12:01:36
【问题描述】:

我有一个想要过滤的大列表。我想通过对列表中的每个元素执行一些操作然后删除来做到这一点 列表中的任何其他匹配元素。所需的输出是较短的ls,并删除了匹配的操作后元素。我可以做到。。但是真的很慢。 你有什么建议可以加快速度吗?

示例列表如下所示:

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)

【问题讨论】:

  • 您的代码不起作用-它在ls.index(elem) 电话中给了我ValueError: 2 is not in list。

标签: python filtering processing-efficiency


【解决方案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))

【讨论】:

  • 我非常喜欢这个解决方案 :) 但唯一的问题是 performOps 返回一个列表,所以我需要附加到 toRemove。
  • @user70434 如果 performOps 返回一个列表,此代码将起作用,因为 for 循环适用于任何可迭代对象。
【解决方案2】:

为什么不将列表转换为集合?这确保了双打已经被删除。 然后扩展 Moinuddin Quadri 的答案

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 方法之前转换为集合并过滤重复项来节省循环时间
  • 这段代码有一个bug:你需要先检查元素是否在集合中,然后再尝试删除它。对于 perfomOps(1),它会返回 (1,1,1),并且在您尝试第二次删除 1 后它会失败。
  • 这就是我在晚上 11 点编码的结果。 @jgfооt 感谢现场
  • @JaseRieger:我是在凌晨 5 点做的:D
【解决方案3】:

您可以使用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 中元素的索引可能会从一次迭代更改为下一次迭代。
  • 更新了我的答案。我正在使用enumerate(list(ls)) 来阻止列表的索引。 list(ls) 将创建ls 的副本。这样迭代将在另一个列表上,并且索引将被阻止。还删除了if i in ls[i+1:] 条件。
  • 更简化了答案。我们不需要枚举器。这就是你要找的东西吗?
猜你喜欢
  • 2023-03-23
  • 2021-12-20
  • 2011-02-09
  • 2017-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-23
  • 2019-04-28
相关资源
最近更新 更多