Python:删除满足特定条件的所有列表索引

时间:2011-08-23 15:19:12

标签: python list indices del

直到它,我正在尝试迭代python中的坐标对列表并删除其中一个坐标为负的所有情况。例如:

数组中的

map = [[-1, 2], [5, -3], [2, 3], [1, -1], [7, 1]]

我想删除其中任何一个坐标都是< 0,离开:

map = [[2, 3], [7, 1]]

我的问题是python列表没有任何空白,所以如果我像这样循环:

i = 0
for pair in map:
        for coord in pair:
            if coord < 0:
                del map[i]
    i += 1

当元素被删除时,所有索引都会移位,弄乱迭代并导致各种问题。我已经尝试将坏元素的索引存储在另一个列表中,然后循环并删除这些元素,但我遇到了同样的问题:一旦消失,整个列表就会移动,索引也不再准确。

有什么我想念的吗?

感谢。

8 个答案:

答案 0 :(得分:3)

您可以使用list comprehension

>>> mymap = [[-1, 2], [5, -3], [2, 3], [1, -1], [7, 1]]
>>> mymap = [m for m in mymap if m[0] > 0 and m[1] > 0]
>>> mymap
[[2, 3], [7, 1]]

答案 1 :(得分:3)

如果列表不大,那么最简单的方法是创建一个新列表:

In [7]: old_map = [[-1, 2], [5, -3], [2, 3], [1, -1], [7, 1]]

In [8]: new_map=[[x,y] for x,y in a_map if not (x<0 or y<0)]

In [9]: new_map
Out[9]: [[2, 3], [7, 1]]

如果您想丢弃其他对,可以使用old_map = new_map进行此操作。

如果列表太大,创建一个可比较大小的新列表是一个问题,那么你可以就地删除列表中的元素 - 诀窍是先从尾端删除它们:

the_map = [[-1, 2], [5, -3], [2, 3], [1, -1], [7, 1]]
for i in range(len(the_map)-1,-1,-1):
    pair=the_map[i]
    for coord in pair:
        if coord < 0:
            del the_map[i]

print(the_map)

产量

[[2, 3], [7, 1]]

PS。 map是一个非常有用的内置Python函数。最好不要命名变量map,因为这会覆盖内置函数。

答案 2 :(得分:1)

如果您没有对map列表的任何其他引用,列表理解效果最佳:

map = [[a,b] for (a,b) in map if a > 0 and b > 0]

如果您确实有其他参考资料,并且需要实际删除map 引用的列表中的元素,则必须迭代map的副本:

for coord in map[:]:
    if coord[0] < 0 or coord[1] < 0:
        map.remove(coord)

答案 3 :(得分:0)

如果您希望在不创建新列表的情况下执行此操作,只需使用索引从len(map)-1下降到0的for循环。

for index in range(len(map)-1,-1,-1):
    if hasNegativeCoord(map[index]):
        del(map[index])

我承认,这不是Pythonic。

答案 4 :(得分:0)

就个人而言,我更喜欢就地修改:

li = [[-1, 2], [5, -3], [2, 3], [1, -1], [7, 1]]
print li,'\n'


N = len(li)
for i,(a,b) in enumerate(li[::-1], start=1):
    if a<0 or b<0:
        del li[N-i]
print li

- &GT;

[[-1, 2], [5, -3], [2, 3], [1, -1], [7, 1]] 

[[2, 3], [7, 1]]

答案 5 :(得分:0)

如果列表足够小,那么制作一个只包含您需要的元素的副本会更有效,详见其他答案。

但是,如果列表太大,或者由于某些其他原因需要从列表对象中删除元素,我发现以下小帮助函数非常有用:< / p>

def filter_in_place(func, target, invert=False):
    "remove all elements of target where func(elem) is false"
    pos = len(target)-1
    while pos >= 0:
        if (not func(target[pos])) ^ invert:
            del target[pos]
        pos -= 1

在您的示例中,可以按如下方式应用:

 >>> data = [[-1, 2], [5, -3], [2, 3], [1, -1], [7, 1]]
 >>> def is_good(elem):
         return elem[0] >= 0 and elem[1] >= 0
 >>> filter_in_place(is_good, data)
 >>> data
 [[2, 3], [7, 1]]

(这只是一个面向列表的filter_in_place版本,支持所有基本Python数据类型的版本有点复杂)。

答案 6 :(得分:0)

itertools.ifilter()/ifilterfalse()存在这样做:通过谓词过滤可迭代(显然不是就地)。 更好的是,如果可能的话,避免创建和分配整个过滤的列表对象,只需迭代它:

import itertools

l = [(4,-5), (-8,2), (-2,-3), (4,7)]

# Option 1: create a new filtered list
l_filtered = list( itertools.ifilter(lambda p: p[0]>0 and p[1]>0, l) )

# Option 2:
for p in itertools.ifilter(lambda p: p[0]>0 and p[1]>0, l):
    ... <subsequent code on your filtered list> 

答案 7 :(得分:-2)

您可能需要del pair