【发布时间】:2015-02-27 06:50:45
【问题描述】:
我正在使用 Python 2.7 解决空间分析问题。我有一个字典 edges 表示图中的边,其中键是 edgeID,值是起点/终点:
{e1: [(12.8254, 55.3880), (12.8343, 55.3920)],
e2: [(12.8254, 55.3880), (12.8235, 55.3857)],
e3: [(12.2432, 57.1120), (12.2426, 57.1122)]}
我还有另一个字典nodes,其中键是节点ID,值是节点坐标:
{n14: (12.8254, 55.3880),
n15: (12.8340, 55.3883),
n16: (12.8235, 55.3857),
n17: (12.8343, 55.3920)}
我需要得到一个看起来像这样的列表(键中的“n”和“e”只是为了说明这个问题,我在那里有整数):
[(e1,n14,n17),(e2,n14,n16)..]
也就是说,我遍历边缘字典,获取每个键,找到存在于nodes 字典中的值并添加到元组中。这就是我现在的做法:
edgesList = []
for featureId in edges:
edgeFeatureId = [k for k, v in edges.iteritems() if k == featureId][0]
edgeStartPoint = [k for k, v in nodes.iteritems() if v == edges[featureId][0]][0]#start point
edgeEndPoint = [k for k, v in nodes.iteritems() if v == edges[featureId][1]][0]#end point
edgesList.append((edgeFeatureId,edgeStartPoint,edgeEndPoint))
这是可行的,但在处理大型数据集时非常慢(100K 边和 90K 节点需要大约 10 分钟)。
我已经弄清楚如何在获取每个元组的项目时使用列表推导,但是是否可以将我的 3 个列表推导合二为一,以避免使用 for 循环迭代边缘(如果这会加快事情了)?
有没有其他方法可以更快地建立这样的列表?
更新
正如 Martin 所建议的,我已经反转了我的节点字典:
nodesDict = dict((v,k) for k,v in oldnodesDict.iteritems())
以节点坐标元组作为键,以节点ID 作为值。不幸的是,它并没有加快查找过程(这里是更新的代码 - 我将k 和v 翻转为edgeStartPoint 和edgeEndPoint):
edgesList = []
for featureId in edges:
edgeFeatureId = [k for k, v in edges.iteritems() if k == featureId][0]
edgeStartPoint = [v for k, v in nodes.iteritems() if k == edges[featureId][0]][0]#start point
edgeEndPoint = [v for k, v in nodes.iteritems() if k == edges[featureId][1]][0]#end point
edgesList.append((edgeFeatureId,edgeStartPoint,edgeEndPoint))
【问题讨论】:
-
你能创建一个代表边缘的对象吗?您可以重载 equal 函数或其他函数以简化使用此数据结构的工作吗?
-
@Marcin,你的意思是为边缘对象创建一个类吗?我希望能够进行某种智能字典匹配,但可以找到任何合适的东西。
-
是的,一个 Edge 类。看起来它可以简单地让你的代码和操作在边缘。
-
好的,感谢您的提示。我试图加速的操作是我将在 Python 中执行的最后一个操作,之前发生的所有数据处理都在几秒钟内发生,这只是最后一部分需要花费大量时间。我想避免为 Edge 创建类,因为我不会将它用于其他任何事情......
-
你为什么到处使用
iteritems(),字典的重点是基于键的查找,iteritems()每次查找都有 O(N) 的性能。要么重新排列您的数据以允许按键查找,要么切换到至少会给出 Olog(n) 的二叉搜索树类型结构。
标签: python list dictionary list-comprehension