代码之家  ›  专栏  ›  技术社区  ›  lfaraone

迭代时如何从列表中删除项?

  •  793
  • lfaraone  · 技术社区  · 15 年前

    我正在迭代Python中的元组列表,并试图在满足某些条件时删除它们。

    for tup in somelist:
        if determine(tup):
             code_to_remove_tup
    

    我应该用什么来代替 code_to_remove_tup ?我不知道如何以这种方式删除这个项目。

    23 回复  |  直到 6 年前
        1
  •  663
  •   Mark Amery Harley Holcombe    8 年前

    可以使用列表理解创建一个仅包含不想删除的元素的新列表:

    somelist = [x for x in somelist if not determine(x)]
    

    或者,通过分配给切片 somelist[:] ,可以改变现有列表,使其仅包含所需的项:

    somelist[:] = [x for x in somelist if not determine(x)]
    

    如果有其他参考资料,这种方法可能很有用 somelist 这需要反映变化。

    除了理解,你还可以使用 itertools . 在Python 2中:

    from itertools import ifilterfalse
    somelist[:] = ifilterfalse(determine, somelist)
    

    或者在Python 3中:

    from itertools import filterfalse
    somelist[:] = filterfalse(determine, somelist)
    
        2
  •  518
  •   Scharron    11 年前

    建议列表理解的答案几乎是正确的——只是他们构建了一个全新的列表,然后给它起与旧列表相同的名称,因为他们没有适当地修改旧列表。这与选择删除不同,如@lennart的建议——它更快,但是如果您的列表是通过多个引用访问的,那么您只是重新放置其中一个引用,而不更改列表对象本身会导致细微的灾难性错误。

    幸运的是,很容易获得列表理解的速度和就地更改所需的语义——只需代码:

    somelist[:] = [tup for tup in somelist if determine(tup)]
    

    注意与其他答案的细微差别:这一个不是分配给一个空名称-它分配给一个恰好是整个列表的列表切片,从而替换列表 内容 在同一个python列表对象中 ,而不是像其他答案一样重新放置一个引用(从以前的列表对象到新的列表对象)。

        3
  •  227
  •   Mark Amery Harley Holcombe    8 年前

    您需要获取列表的一个副本,并首先对其进行迭代,否则迭代将失败,并可能导致意外的结果。

    例如(取决于列表的类型):

    for tup in somelist[:]:
        etc....
    

    一个例子:

    >>> somelist = range(10)
    >>> for x in somelist:
    ...     somelist.remove(x)
    >>> somelist
    [1, 3, 5, 7, 9]
    
    >>> somelist = range(10)
    >>> for x in somelist[:]:
    ...     somelist.remove(x)
    >>> somelist
    []
    
        4
  •  98
  •   Jean-François Fabre    6 年前
    for i in range(len(somelist) - 1, -1, -1):
        if some_condition(somelist, i):
            del somelist[i]
    

    你需要向后走,否则就有点像锯掉你坐在上面的树枝。

    python 2用户:替换 range 通过 xrange 避免创建硬编码列表

        5
  •  46
  •   Eli Courtwright    15 年前

    对于这样一个例子,您最好的方法是 list comprehension

    somelist = [tup for tup in somelist if determine(tup)]
    

    如果你做的事情比打电话给 determine 函数,我更喜欢构造一个新的列表,并在执行过程中简单地附加到它。例如

    newlist = []
    for tup in somelist:
        # lots of code here, possibly setting things up for calling determine
        if determine(tup):
            newlist.append(tup)
    somelist = newlist
    

    使用复制列表 remove 可能会使代码看起来更干净一些,如下面的一个答案所述。对于非常大的列表,您绝对不应该这样做,因为这涉及到首先复制整个列表,并执行 O(n) 去除 为要移除的每个元素执行的操作,使其成为 O(n^2) 算法。

    for tup in somelist[:]:
        # lots of code here, possibly setting things up for calling determine
        if determine(tup):
            newlist.append(tup)
    
        6
  •  38
  •   Ciro Santilli OurBigBook.com    7 年前

    这个 official Python 2 tutorial 4.2. "for Statements" :

    如果您需要在循环内修改正在迭代的序列(例如复制选定的项),建议您首先进行复制。迭代序列不会隐式生成副本。切片符号使得这一点特别方便:

    >>> for w in words[:]:  # Loop over a slice copy of the entire list.
    ...     if len(w) > 6:
    ...         words.insert(0, w)
    ...
    >>> words
    ['defenestrate', 'cat', 'window', 'defenestrate']
    

    建议如下: https://stackoverflow.com/a/1207427/895245

    这个 Python 2 documentation 7.3. "The for statement" 给出同样的建议 :

    注意:当序列被循环修改时有一个微妙的地方(这只能发生在可变序列,即列表中)。内部计数器用于跟踪下一个使用的项,并在每次迭代中递增。当这个计数器达到序列的长度时,循环终止。这意味着,如果套件从序列中删除当前(或上一个)项目,则将跳过下一个项目(因为它获取已处理的当前项目的索引)。同样,如果套件在当前项之前按顺序插入一个项,则下次将通过循环再次处理当前项。这可能导致严重的错误,可以通过使用整个序列的一个切片进行临时复制来避免,例如,

    for x in a[:]:
        if x < 0: a.remove(x)
    

    巨蟒能做得更好吗?

    似乎可以改进这个特定的python API。比较它,例如,它的Java对应 ListIterator 这就清楚地表明,除了使用迭代器本身之外,您不能修改正在迭代的列表,并提供了在不复制列表的情况下进行修改的有效方法。来吧,巨蟒!

        7
  •  36
  •   Tim Abhishek Kumar    8 年前

    对于那些喜欢函数式编程的人:

    somelist[:] = filter(lambda tup: not determine(tup), somelist)
    

    from itertools import ifilterfalse
    somelist[:] = list(ifilterfalse(determine, somelist))
    
        8
  •  10
  •   ntk4    8 年前

    如果当前列表项满足所需的条件,也可以创建新列表。

    所以:

    for item in originalList:
       if (item != badValue):
            newList.append(item)
    

    为了避免用新列表名称重新编码整个项目:

    originalList[:] = newList
    

    注意,在python文档中:

    复印件(X) 返回X的浅色副本。

    副本.deepcopy(x) 返回X的深度副本。

        9
  •  10
  •   Michael    7 年前

    我需要用一个巨大的列表来完成这项工作,并且复制这个列表似乎很昂贵,特别是在我的例子中,与保留的项目相比,删除的数量是很少的。我采取了这种低级的方法。

    array = [lots of stuff]
    arraySize = len(array)
    i = 0
    while i < arraySize:
        if someTest(array[i]):
            del array[i]
            arraySize -= 1
        else:
            i += 1
    

    我不知道与复制一个大列表相比,两个删除的效率有多高。如果您有任何见解,请发表评论。

        10
  •  8
  •   Community datashaman    7 年前

    此答案最初是针对已标记为重复的问题编写的: Removing coordinates from list on python

    代码中有两个问题:

    1)当使用remove()时,您尝试移除整数,而需要移除元组。

    2)for循环将跳过列表中的项目。

    让我们来看看在执行代码时会发生什么:

    >>> L1 = [(1,2), (5,6), (-1,-2), (1,-2)]
    >>> for (a,b) in L1:
    ...   if a < 0 or b < 0:
    ...     L1.remove(a,b)
    ... 
    Traceback (most recent call last):
      File "<stdin>", line 3, in <module>
    TypeError: remove() takes exactly one argument (2 given)
    

    第一个问题是您将“a”和“b”同时传递给remove(),但remove()只接受一个参数。那么我们如何才能让remove()正确地处理您的列表呢?我们需要弄清楚您列表中的每个元素是什么。在这种情况下,每个都是一个元组。要看到这个,让我们访问列表中的一个元素(索引从0开始):

    >>> L1[1]
    (5, 6)
    >>> type(L1[1])
    <type 'tuple'>
    

    啊哈!l1的每个元素实际上是一个元组。所以这就是我们需要传递来移除()的内容。python中的元组非常简单,只需将值括在括号中就可以了。”a,b“不是一个元组,但”(a,b)“是一个元组。因此,我们修改您的代码并再次运行它:

    # The remove line now includes an extra "()" to make a tuple out of "a,b"
    L1.remove((a,b))
    

    此代码运行时没有任何错误,但让我们看看它输出的列表:

    L1 is now: [(1, 2), (5, 6), (1, -2)]
    

    为什么(1,-2)仍然在您的列表中?事实证明,在使用循环迭代列表的同时修改列表是一个非常糟糕的主意,不需要特别注意。(1,-2)保留在列表中的原因是,在for循环的迭代之间,列表中每个项的位置都发生了更改。让我们看看如果我们向上面的代码提供一个更长的列表会发生什么:

    L1 = [(1,2),(5,6),(-1,-2),(1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
    ### Outputs:
    L1 is now: [(1, 2), (5, 6), (1, -2), (3, 4), (5, 7), (2, 1), (5, -1), (0, 6)]
    

    从结果中可以推断,每当条件语句的计算结果为true并且移除列表项时,循环的下一次迭代将跳过对列表中下一项的计算,因为其值现在位于不同的索引中。

    最直观的解决方案是复制列表,然后迭代原始列表,只修改副本。您可以这样做:

    L2 = L1
    for (a,b) in L1:
        if a < 0 or b < 0 :
            L2.remove((a,b))
    # Now, remove the original copy of L1 and replace with L2
    print L2 is L1
    del L1
    L1 = L2; del L2
    print ("L1 is now: ", L1)
    

    但是,输出将与之前相同:

    'L1 is now: ', [(1, 2), (5, 6), (1, -2), (3, 4), (5, 7), (2, 1), (5, -1), (0, 6)]
    

    这是因为当我们创建L2时,python实际上并没有创建新的对象。相反,它只是将l2引用到与l1相同的对象。我们可以用“is”来验证这一点,它与“equals”(==)不同。

    >>> L2=L1
    >>> L1 is L2
    True
    

    我们可以使用copy.copy()生成一个真正的副本。然后一切按预期工作:

    import copy
    L1 = [(1,2), (5,6),(-1,-2), (1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
    L2 = copy.copy(L1)
    for (a,b) in L1:
        if a < 0 or b < 0 :
            L2.remove((a,b))
    # Now, remove the original copy of L1 and replace with L2
    del L1
    L1 = L2; del L2
    >>> L1 is now: [(1, 2), (5, 6), (3, 4), (5, 7), (2, 1), (0, 6)]
    

    最后,还有一个比制作一个全新的L1副本更干净的解决方案。reversed()函数:

    L1 = [(1,2), (5,6),(-1,-2), (1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
    for (a,b) in reversed(L1):
        if a < 0 or b < 0 :
            L1.remove((a,b))
    print ("L1 is now: ", L1)
    >>> L1 is now: [(1, 2), (5, 6), (3, 4), (5, 7), (2, 1), (0, 6)]
    

    不幸的是,我无法充分描述revered()的工作方式。当一个列表传递给它时,它返回一个“listReverseIterator”对象。出于实际目的,您可以将其视为创建其论点的反向副本。这是我推荐的解决方案。

        11
  •  4
  •   fantabolous    10 年前

    如果您想在迭代过程中执行其他操作,那么最好同时获取索引(这可以保证您能够引用它,例如,如果您有一个dict列表)和实际的列表项内容。

    inlist = [{'field1':10, 'field2':20}, {'field1':30, 'field2':15}]    
    for idx, i in enumerate(inlist):
        do some stuff with i['field1']
        if somecondition:
            xlist.append(idx)
    for i in reversed(xlist): del inlist[i]
    

    enumerate 允许您立即访问该项和索引。 reversed 这样,以后要删除的索引就不会改变。

        12
  •  4
  •   Bharat Mane Xolve    7 年前

    你可能想用 filter() 内置。

    有关详细信息 check here

        13
  •  3
  •   Queequeg    9 年前

    您可以尝试反向循环,因此对于某些列表,您可以执行如下操作:

    list_len = len(some_list)
    for i in range(list_len):
        reverse_i = list_len - 1 - i
        cur = some_list[reverse_i]
    
        # some logic with cur element
    
        if some_condition:
            some_list.pop(reverse_i)
    

    这样索引就可以对齐,并且不会受到列表更新的影响(不管是否弹出cur元素)。

        14
  •  3
  •   Xenolion ariochdivij666    6 年前

    一个可能的解决方案,如果您不仅想删除某些内容,而且还想在单个循环中对所有元素执行某些操作,那么它很有用:

    alist = ['good', 'bad', 'good', 'bad', 'good']
    i = 0
    for x in alist[:]:
        if x == 'bad':
            alist.pop(i)
            i -= 1
        # do something cool with x or just print x
        print(x)
        i += 1
    
        15
  •  2
  •   rafa    9 年前

    我需要做一些类似的事情,在我的例子中,问题是内存——我需要在一个列表中合并多个数据集对象,在对它们做了一些事情之后,作为一个新的对象,并且需要去掉我正在合并的每个条目,以避免复制所有的数据集对象,并炸毁内存。在我的例子中,将对象放在字典中而不是列表中可以很好地工作:

    ` `

    k = range(5)
    v = ['a','b','c','d','e']
    d = {key:val for key,val in zip(k, v)}
    
    print d
    for i in range(5):
        print d[i]
        d.pop(i)
    print d
    

    ` `

        16
  •  2
  •   Community datashaman    7 年前

    TLDR:

    我写了一个图书馆,允许你这样做:

    from fluidIter import FluidIterable
    fSomeList = FluidIterable(someList)  
    for tup in fSomeList:
        if determine(tup):
            # remove 'tup' without "breaking" the iteration
            fSomeList.remove(tup)
            # tup has also been removed from 'someList'
            # as well as 'fSomeList'
    

    如果可能的话,最好使用另一种方法,在迭代ITerable时不需要修改它,但是对于某些算法,它可能不是那么直接的。因此,如果您确定您确实想要原始问题中描述的代码模式,那么这是可能的。

    应该处理所有可变序列,而不仅仅是列表。


    完全回答:

    编辑:此答案中的最后一个代码示例给出了 为什么? 有时您可能希望在适当的位置修改列表,而不是使用列表理解。答案的第一部分作为 怎样 可以就地修改数组。

    解决方法如下: this 回答(有关问题)。这解释了在遍历已修改的列表时如何更新数组索引。下面的解决方案旨在正确跟踪数组索引,即使修改了列表。

    下载 fluidIter.py here https://github.com/alanbacon/FluidIterator ,它只是一个文件,所以不需要安装git。没有安装程序,因此您需要确保文件在自己的python路径中。代码是为python 3编写的,没有在python 2上测试过。

    from fluidIter import FluidIterable
    l = [0,1,2,3,4,5,6,7,8]  
    fluidL = FluidIterable(l)                       
    for i in fluidL:
        print('initial state of list on this iteration: ' + str(fluidL)) 
        print('current iteration value: ' + str(i))
        print('popped value: ' + str(fluidL.pop(2)))
        print(' ')
    
    print('Final List Value: ' + str(l))
    

    这将产生以下输出:

    initial state of list on this iteration: [0, 1, 2, 3, 4, 5, 6, 7, 8]
    current iteration value: 0
    popped value: 2
    
    initial state of list on this iteration: [0, 1, 3, 4, 5, 6, 7, 8]
    current iteration value: 1
    popped value: 3
    
    initial state of list on this iteration: [0, 1, 4, 5, 6, 7, 8]
    current iteration value: 4
    popped value: 4
    
    initial state of list on this iteration: [0, 1, 5, 6, 7, 8]
    current iteration value: 5
    popped value: 5
    
    initial state of list on this iteration: [0, 1, 6, 7, 8]
    current iteration value: 6
    popped value: 6
    
    initial state of list on this iteration: [0, 1, 7, 8]
    current iteration value: 7
    popped value: 7
    
    initial state of list on this iteration: [0, 1, 8]
    current iteration value: 8
    popped value: 8
    
    Final List Value: [0, 1]
    

    上面我们用了 pop 流体列表对象上的方法。还实现了其他常见的可迭代方法,例如 del fluidL[i] , .remove , .insert , .append , .extend . 也可以使用切片修改列表( sort reverse 方法未实现)。

    唯一的条件是,如果在任何时候 fluidL l 已重新分配给其他列表对象,代码将不起作用。原文 流态化 对象仍将由for循环使用,但将超出我们修改的范围。

    fluidL[2] = 'a'   # is OK
    fluidL = [0, 1, 'a', 3, 4, 5, 6, 7, 8]  # is not OK
    

    如果要访问列表的当前索引值,则不能使用枚举,因为这只计算for循环已运行的次数。相反,我们将直接使用迭代器对象。

    fluidArr = FluidIterable([0,1,2,3])
    # get iterator first so can query the current index
    fluidArrIter = fluidArr.__iter__()
    for i, v in enumerate(fluidArrIter):
        print('enum: ', i)
        print('current val: ', v)
        print('current ind: ', fluidArrIter.currentIndex)
        print(fluidArr)
        fluidArr.insert(0,'a')
        print(' ')
    
    print('Final List Value: ' + str(fluidArr))
    

    这将输出以下内容:

    enum:  0
    current val:  0
    current ind:  0
    [0, 1, 2, 3]
    
    enum:  1
    current val:  1
    current ind:  2
    ['a', 0, 1, 2, 3]
    
    enum:  2
    current val:  2
    current ind:  4
    ['a', 'a', 0, 1, 2, 3]
    
    enum:  3
    current val:  3
    current ind:  6
    ['a', 'a', 'a', 0, 1, 2, 3]
    
    Final List Value: ['a', 'a', 'a', 'a', 0, 1, 2, 3]
    

    这个 FluidIterable 类只是为原始列表对象提供包装。原始对象可以作为流体对象的属性访问,如下所示:

    originalList = fluidArr.fixedIterable
    

    更多示例/测试可在 if __name__ is "__main__": 底部的部分 流体迭代 . 这些值得一看,因为它们解释了在各种情况下发生的事情。例如:使用一个切片替换列表中的大部分。或者在嵌套for循环中使用(和修改)相同的iterable。

    正如我前面所说:这是一个复杂的解决方案,它会损害代码的可读性,并使调试更加困难。因此,其他解决方案,如大卫·拉兹尼克所提到的清单理解 answer 应该首先考虑。也就是说,我发现这个类对我有用的时候,比跟踪需要删除的元素的索引更容易使用。


    编辑:正如评论中所提到的,这个答案并没有真正提出一个问题,这个方法为这个问题提供了解决方案。我将尝试在这里解决这个问题:

    列表理解提供了一种生成新列表的方法,但是这些方法倾向于孤立地查看每个元素,而不是将列表的当前状态作为一个整体。

    newList = [i for i in oldList if testFunc(i)]
    

    但是如果结果是 testFunc 取决于已添加到 newList 已经?或者元素还在 oldList 下一步可能会添加?也许还有一种方法可以使用列表理解,但它将开始失去它的优雅,对我来说,在适当的位置修改列表更容易。

    下面的代码是遭受上述问题的算法的一个例子。该算法将减少一个列表,使任何元素都不是任何其他元素的倍数。

    randInts = [70, 20, 61, 80, 54, 18, 7, 18, 55, 9]
    fRandInts = FluidIterable(randInts)
    fRandIntsIter = fRandInts.__iter__()
    # for each value in the list (outer loop)
    # test against every other value in the list (inner loop)
    for i in fRandIntsIter:
        print(' ')
        print('outer val: ', i)
        innerIntsIter = fRandInts.__iter__()
        for j in innerIntsIter:
            innerIndex = innerIntsIter.currentIndex
            # skip the element that the outloop is currently on
            # because we don't want to test a value against itself
            if not innerIndex == fRandIntsIter.currentIndex:
                # if the test element, j, is a multiple 
                # of the reference element, i, then remove 'j'
                if j%i == 0:
                    print('remove val: ', j)
                    # remove element in place, without breaking the
                    # iteration of either loop
                    del fRandInts[innerIndex]
                # end if multiple, then remove
            # end if not the same value as outer loop
        # end inner loop
    # end outerloop
    
    print('')
    print('final list: ', randInts)
    

    输出和最终缩减列表如下所示

    outer val:  70
    
    outer val:  20
    remove val:  80
    
    outer val:  61
    
    outer val:  54
    
    outer val:  18
    remove val:  54
    remove val:  18
    
    outer val:  7
    remove val:  70
    
    outer val:  55
    
    outer val:  9
    remove val:  18
    
    final list:  [20, 61, 7, 55, 9]
    
        17
  •  1
  •   Beefster    6 年前

    其他的答案是正确的,从正在迭代的列表中删除通常是一个坏主意。反向迭代可以避免这些陷阱,但是遵循这样做的代码要困难得多,因此通常最好使用列表理解或 filter .

    但是,有一种情况是可以安全地从正在迭代的序列中删除元素:如果在迭代时只删除一个项。这可以通过使用 return 或A break . 例如:

    for i, item in enumerate(lst):
        if item % 4 == 0:
            foo(item)
            del lst[i]
            break
    

    当您对满足某些条件的列表中的第一个项目执行一些具有副作用的操作,然后在之后立即从列表中删除该项目时,这通常比列表理解更容易理解。

        18
  •  1
  •   Mujeeb    6 年前

    这里的大多数答案都希望您创建列表的副本。我有一个用例,其中的列表很长(11000个项目),所以最好继续减少列表。

    首先,你需要 用while循环替换foreach循环 ,

    i = 0
    while i < len(somelist):
        if determine(somelist[i]):
             del somelist[i]
        else:
            i += 1
    

    价值 i 不会在if块中更改,因为删除旧项后,您将希望从同一索引中获取新项的值。

        19
  •  1
  •   chseng    6 年前

    最有效的方法是列表理解,很多人展示他们的案例,当然,这也是获得 iterator 通过 filter .

    Filter 接收函数和序列。 滤波器 依次将传递的函数应用于每个元素,然后根据函数返回值是 True False .

    有一个例子(从元组中得到赔率):

    list(filter(lambda x:x%2==1, (1, 2, 4, 5, 6, 9, 10, 15)))  
    # result: [1, 5, 9, 15]
    

    注意:您也不能处理迭代器。迭代器有时比序列更好。

        20
  •  1
  •   Siddharth Satpathy    6 年前

    我可以想出三种方法来解决你的问题。例如,我将创建一个元组的随机列表 somelist = [(1,2,3), (4,5,6), (3,6,6), (7,8,9), (15,0,0), (10,11,12)] . 我选择的条件是 sum of elements of a tuple = 15 . 在最后一个列表中,我们将只包含总和不等于15的元组。

    我选择的是一个随机选择的例子。 随时改变 这个 元组列表 以及 条件 我选择的。

    方法1 .gt; 使用您建议的框架(在for循环中填充代码)。我用一个小代码 del 删除满足上述条件的元组。但是,如果两个连续放置的元组满足给定条件,则此方法将缺少一个元组(满足上述条件)。

    for tup in somelist:
        if ( sum(tup)==15 ): 
            del somelist[somelist.index(tup)]
    
    print somelist
    >>> [(1, 2, 3), (3, 6, 6), (7, 8, 9), (10, 11, 12)]
    

    方法2 .gt; 构造一个新列表,其中包含不满足给定条件的元素(元组)(这与删除满足给定条件的列表元素相同)。代码如下:

    newlist1 = [somelist[tup] for tup in range(len(somelist)) if(sum(somelist[tup])!=15)]
    
    print newlist1
    >>>[(1, 2, 3), (7, 8, 9), (10, 11, 12)]
    

    方法3 .gt; 找到满足给定条件的索引,然后使用与这些索引对应的移除元素(元组)。下面是代码。

    indices = [i for i in range(len(somelist)) if(sum(somelist[i])==15)]
    newlist2 = [tup for j, tup in enumerate(somelist) if j not in indices]
    
    print newlist2
    >>>[(1, 2, 3), (7, 8, 9), (10, 11, 12)]
    

    方法1和方法2比方法3快 . 方法2和方法3比方法1更有效。我 首选方法2 . 对于上述示例, time(method1) : time(method2) : time(method3) = 1 : 1 : 1.7

        21
  •  0
  •   CENTURION    6 年前

    对于任何可能非常大的项目,我都使用以下内容。

    import numpy as np
    
    orig_list = np.array([1, 2, 3, 4, 5, 100, 8, 13])
    
    remove_me = [100, 1]
    
    cleaned = np.delete(orig_list, remove_me)
    print(cleaned)
    

    这应该比其他任何事情都快得多。

        22
  •  0
  •   MathKid    6 年前

    在某些情况下,当您不仅仅是一次过滤一个列表项时,您希望在迭代时更改迭代。

    这里有一个示例,其中预先复制列表是不正确的,反向迭代是不可能的,并且列表理解也不是一个选项。

    """ Sieve of Eratosthenes """
    
    def generate_primes(n):
        """ Generates all primes less than n. """
        primes = list(range(2,n))
        idx = 0
        while idx < len(primes):
            p = primes[idx]
            for multiple in range(p+p, n, p):
                try:
                    primes.remove(multiple)
                except ValueError:
                    pass #EAFP
            idx += 1
            yield p
    
        23
  •  -1
  •   Nathan Tuggy TonyLuigiC    7 年前

    现在您想要创建一个列表的副本,这样当您迭代和删除该列表中满足特定条件的元组时,可以将其作为引用。

    然后,它取决于您希望输出的列表类型,无论是已删除元组的列表还是未删除的元组的列表。

    正如大卫指出的,我建议列表理解来保留不想删除的元素。

    somelist = [x for x in somelist if not determine(x)]