我有一个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
的索引?
有谁知道更有效的解决方案?
答案 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)