5

为了深入了解它,我正在尝试遍历 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

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

有什么我想念的吗?

谢谢。

4

8 回答 8

3

您可以为此使用列表推导:

>>> 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]]
于 2011-08-23T15:21:05.943 回答
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,因为这会覆盖内置变量。

于 2011-08-23T15:23:18.127 回答
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)
于 2011-08-23T15:27:55.877 回答
0

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

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

我承认,不是很 Pythonic。

于 2011-08-23T15:31:16.593 回答
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

->

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

[[2, 3], [7, 1]]
于 2011-08-23T16:25:21.373 回答
0

如果列表足够小,则制作仅包含所需元素的副本会更有效,如其他答案中所述。

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

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 数据类型的版本有点复杂)。

于 2011-08-24T01:30:13.790 回答
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> 
于 2013-11-12T00:03:52.897 回答
-2

你可能想要del pair

于 2011-08-23T17:15:38.447 回答