我正在尝试对点列表(他们的ID)进行排序。元组是图的最小生成树(使用networkx)的结果,其中每个节点都连接到每个其他节点,但它们的权重不同。我需要为每个树提取(最短)路径,这将给出正确的边缘顺序。但是MST的元组的结果是无序的,如果我按原样使用它,我会得到不好的结果,所以我需要对tupes进行排序。我有一些元组的示例列表:
L1: [(0, 1), (0, 3), (2, 3)]
L2: [(0, 3), (1, 2), (2, 3)]
L3: [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
L1和L2没有按我的要求排序,L3是。您可能会注意到,我需要列表的顺序是后续的点/元组,以获得树的顺序。 L1和L2需要按如下方式排序:
L1: [(1, 0), (0, 3), (3, 2)] : order = 1-0-3-2
L2: [(0, 3), (3, 2), (2, 1)] : order = 0-3-2-1
# some way to do this in pseudo code would be
for tuple in list:
# compare current tuple with previous and next (if exist)
if tuple[1] != next[0]:
reverse tuple
if tuple[0] != prev[1]:
reverse tuple
etc...
我试图通过定义多个if / elif语句(见上文)对列表进行排序,但这会变得混乱和混乱。我已经看过像sorted(L1, key=customsort)
这样的东西排序,但我找不到比较多个元组的方法,我希望这样的事情是可能的!
答案 0 :(得分:1)
最简单的方法是找到路径的起点,根据注释,它是出现一次的两个索引之一,同时构建一个连续遍历的方法。假设n
节点我们可以构建一些东西来帮助我们(这个解决方案我认为是清晰的,线性的,但可能不是最好的/最优雅的):
path = [[] for _ in range(n)]
stops= [2 for _ in range(n)]
for edge in result:
for i in range(2):
path[edge[i]].append(edge[1-i])
stops[edge[i]] -= 1
for current in range(len(stops)):
if stops[current]: break
path
这里保存每个索引(它是一个节点)它连接的两个/一个其他节点。内循环查看边缘中的点 - edge[0],edge[1]
。 1-i
只是将1翻转为0。
stops
计算节点出现的次数。每个节点在路径中出现两次,除了两个 - 这些将是数组中唯一不是0的位置。这不是必须的,只是一个简单的起点。
current
查找这样的非零条目。
现在通过遍历路径来重建,以便根据需要创建正确的元组列表:
result = [(current,path[current][0])] #Only one option!
current= path[current][0]
while stops[current]:
next = path[current][1] if path[current][0] == current else path[current][0]
result.append((current,next))
current = next
注意我没有使用原始列表中的一些知识,例如订单。您可以使用它来改善这一点。
答案 1 :(得分:0)
我决定尝试改进上述答案,并使个别操作更简单。
import collections
def sort_mst(lst):
unordered = [frozenset(elem) for elem in lst]
elems = collections.defaultdict(set)
for elem in unordered:
# Assumption: elem has length 2
for index in elem:
# Assumption: each set will have an elem added no more than twice.
elems[index].add(elem)
# For theoretically faster, but non-deterministic behavior, use next()
# instead of min()
index = min(k for k, v in elems.items() if len(v) == 1)
results = []
while elems[index]:
connection, = elems[index]
next_index, = connection - {index}
results.append((index, next_index))
index = next_index
elems[index] -= {connection}
return results
这使用集合来丢弃不需要的订购信息。它首先将所有元组转换为集合,然后创建从索引到包含它们的集合的反向映射。
接下来,它找到一个仅与一个集相关联的索引,并使用它来遍历反向映射,在将它们添加到输出列表时从中丢弃集。当没有与索引关联的集合时,在丢弃前面的集合之后,它知道它到达另一端,并且完成了。