列表编辑的有效算法

时间:2013-11-22 13:21:52

标签: python list

我有一个3D点云,保存在两个列表中。 5点(x,y,z)的例子:(3,3,3),(1,1,1),(4,4,4),(2,2,2),(5,5,5) ) - >我的列表看起来像这样:

z = [3, 1, 4, 2, 5] # the z values
pts = [(3,3), (1,1), (4,4), (2,2), (5,5)] # the x and y values

现在我想要消除z值大于3的所有值:

# what I want to receive:
z = [3, 1, 2]
pts = [(3,3), (1,1), (2,2)]

我的算法在这里:

k = -1
for i in range(len(z)):
    k += 1
    if z[k] > h:
        z.pop(k)
        pts.pop(k)
        k -= 1

这正是我想要的 - 但它非常慢(对于> 100,000的值)。 我考虑过首先通过z.sort()对我的列表进行排序,然后执行z = z [:index] - 但是当我为我的z-list执行此操作时,我的pts-list仍未排序。即使我可以对这两个列表进行排序,我也不得不通过一个很长的loop找到我的条件为true的索引? 有谁知道更有效的解决方案?

3 个答案:

答案 0 :(得分:4)

使用itertools:

from itertools import izip, ifilter
拉链

zipped_coords = izip(z, pts)

过滤(在帖子中你提到higher,但是实际结果实际上较低,先选择一个)

filtered_coords = ifilter(lambda x: x[0]>=3, zipped_coords )

解压

znew, ptsnew = map(list, izip(*filtered_coords))

或一体化oneliner

>>> znew, ptsnew = map(list, izip(*ifilter(lambda x: x[0]>=3, izip(z, pts))))
>>> print znew, ptsnew
[3, 4, 5] [(3, 3), (4, 4), (5, 5)]

答案 1 :(得分:4)

z, pts = zip(*[(z, pt) for z, pt in zip(z, pts) if z <= 3])
print z, pts

<强>输出

(3, 1, 2) ((3, 3), (1, 1), (2, 2))

答案 2 :(得分:2)

因为您在迭代时从列表中删除元素,所以它是O(N ^ 2)算法。您可以使用简单的列表推导和zip在线性时间内完成此操作。

z = [3, 1, 4, 2, 5] # the z values
pts = [(3,3), (1,1), (4,4), (2,2), (5,5)] # the x and y values

merged = zip(z, pts)    
filtered = [x for x in merged if x[0] <= 3]
z, pts = zip(*filtered)