联合Python中的列表列表

时间:2014-02-27 23:11:29

标签: python list optimization coding-style pop

我编写了这个程序来计算一组点的3d距离。

points = [(472765.09, 6191522.78, 13.0), (472764.82, 6191524.09, 9.0), (472763.8, 6191525.68, 8.0), (472764.07, 6191524.39, 16.0)]


def dist3d((x0, y0, z0), (x1, y1, z1)):
    return math.sqrt((x0-x1)**2+(y0-y1)**2+(z0-z1)**2)

def dist_3d(obs):
    dist_list = list()
    while len(obs) != 1:
        obs_g = [(obs[0], x) for x in obs[1:]]
        dist_list.append([dist3d(obs_g[i][0], obs_g[i][1]) for i in xrange(len(obs_g))])
        obs.pop(0)
    return dist_list

结果是距离列表列表:

test = dist_3d(points)
print test
[[4.217700795331081, 5.922339064664832, 3.554222840244929], [2.1374049685457694, 7.046453008421205], [8.107835716151763]]

我希望得到的结果如下:

[4.217700795331081, 5.922339064664832, 3.554222840244929, 2.1374049685457694, 7.046453008421205, 8.107835716151763]

P.S。:代码未优化,因为函数返回后只有一个元素的“points”列表

points = [(472765.09, 6191522.78, 13.0), (472764.82, 6191524.09, 9.0), (472763.8, 6191525.68, 8.0), (472764.07, 6191524.39, 16.0)]
test = dist_3d(points)
points
[(472764.07, 6191524.39, 16.0)]

2 个答案:

答案 0 :(得分:1)

要解决您的第一个问题,请在此行中使用list.extend

dist_list.append([dist3d(obs_g[i][0], obs_g[i][1]) for i in xrange(len(obs_g))])

如:

          ######
dist_list.extend([dist3d(obs_g[i][0], obs_g[i][1]) for i in xrange(len(obs_g))])
          ######

Here证明了为什么会有所帮助。


你的第二个问题来自这一行:

obs.pop(0)

由于obspoints都引用相同的列表对象,因此调用obs.pop与直接调用points.pop相同。换句话说,每次执行该行时,都会从points中弹出一个项目。最后,这会导致points只包含一个项目。

要解决此问题,请在points内添加dist_3d的浅表副本:

copy = obs[:]

然后,在副本上调用pop。这样做会使points不受影响。


以下是修改后的代码的外观:

import math

points = [(472765.09, 6191522.78, 13.0), (472764.82, 6191524.09, 9.0), (472763.8, 6191525.68, 8.0), (472764.07, 6191524.39, 16.0)]

def dist3d((x0, y0, z0), (x1, y1, z1)):
    return math.sqrt((x0-x1)**2+(y0-y1)**2+(z0-z1)**2)

def dist_3d(obs):
    dist_list = list()
    copy = obs[:]
    while len(copy) != 1:
        obs_g = [(copy[0], x) for x in copy[1:]]
        dist_list.extend([dist3d(obs_g[i][0], obs_g[i][1]) for i in xrange(len(obs_g))])
        copy.pop(0)
    return dist_list

这是一个示例运行:

>>> import math
>>> points = [(472765.09, 6191522.78, 13.0), (472764.82, 6191524.09, 9.0), (472763.8, 6191525.68, 8.0), (472764.07, 6191524.39, 16.0)]
>>> def dist3d((x0, y0, z0), (x1, y1, z1)):
...     return math.sqrt((x0-x1)**2+(y0-y1)**2+(z0-z1)**2)
...
>>> def dist_3d(obs):
...     dist_list = list()
...     copy = obs[:]
...     while len(copy) != 1:
...         obs_g = [(copy[0], x) for x in copy[1:]]
...         dist_list.extend([dist3d(obs_g[i][0], obs_g[i][1]) for i in xrange(len(obs_g))])
...         copy.pop(0)
...     return dist_list
...
>>> test = dist_3d(points)
>>> print test
[4.217700795331081, 5.922339064664832, 3.554222840244929, 2.1374049685457694, 7.046453008421205, 8.107835716151763]
>>> print points
[(472765.09, 6191522.78, 13.0), (472764.82, 6191524.09, 9.0), (472763.8, 6191525.68, 8.0), (472764.07, 6191524.39, 16.0)]
>>>

答案 1 :(得分:0)

import itertools

def dist_3d(obs):
    dist_list = list()
    while len(obs) != 1:
        obs_g = [(obs[0], x) for x in obs[1:]]
        dist_list.append([dist3d(obs_g[i][0], obs_g[i][1]) for i in xrange(len(obs_g))])
        obs.pop(0)
    return list(itertools.chain(*dist_list))