通过实际列表的值对python中的字典进行排序

问题描述 投票:4回答:3

如果给出一个字典来表示图形,其中顶点是键,值是列表,其条目包含邻居顶点和两个顶点之间的权重,如何以递增的顺序返回边缘列表而不重复?例如,我可能会得到以下字典......:

{“A”:[[“B”,10],[“D”,5]],“B”:[[“A”,10],[“C”,5]],“C”:[ [“B”,5],[“D”,15]],“D”:[[“C”,15],[“A”,5]]}。

此外,我只允许导入副本库,因此我可以复制一个列表并使用deepcopy()创建具有相同元素的新对象。

现在,我正在尝试将字典转换为列表,因为我认为对列表中的元素进行排序可能更容易,并删除重复的边缘。所以目前我有以下内容(图表是字典,在这种情况下是我上面提供的字典)...

def edge_get(graph):

    input_list = []
    sorted_list = []

    for key, value in graph.items():
        temp = [key,value]
        input_list.append(temp)

    print(input_list)

打印出......

[['A',[['B',10],['D',5]]],['B',[['A',10],['C',5]]],[ 'C',[['B',5],['D',15]]],['D',[['C',15],['A',5]]]]

我想把它输出:

[['A','B',10],['A','D',5],['B','A',10],['B','C',5] ,. ..

我想如果我可以这样得到它,我可以比较列表中每个列表的第三个元素,如果它们是相同的,检查其他元素是否匹配(相同的边缘)。基于此,我可以将其添加到最终列表中或忘记它并继续前进。

对于这个例子,最终目标是:

[['A','D'],['B','C'],['A','B'],['C','D']]

python python-3.x list dictionary nested-lists
3个回答
3
投票

因此,您有一个将图形表示为邻接列表的dict,并且您希望将该邻接列表转换为边缘列表。

你可以使用嵌套列表理解来做到这一点:

graph = {"A": [["B",10], ["D",5]], "B": [["A",10], ["C",5]], "C": [["B",5],["D",15]], "D": [["C",15], ["A",5]]}
edges = [(src, dst, weight) for src, adjs in graph.items() for dst, weight in adjs]
# edges = [('A', 'B', 10), ('A', 'D', 5), ('B', 'A', 10), ('B', 'C', 5), ('C', 'B', 5), ('C', 'D', 15), ('D', 'C', 15), ('D', 'A', 5)]

然后你可以通过转换为dict来消除重复边缘,请注意,如果你有重复冲突权重的边缘,这将任意选择一个权重:

uniques = {frozenset([src, dst]): weight for src, dst, weight in edges}
# uniques = {frozenset({'B', 'A'}): 10, frozenset({'A', 'D'}): 5, frozenset({'B', 'C'}): 5, frozenset({'C', 'D'}): 15}

然后使用sorted排序边缘:

sorted_uniques = sorted(uniques.items(), key=lambda v: v[1])
# sorted_uniques = [(frozenset({'A', 'D'}), 5), (frozenset({'C', 'B'}), 5), (frozenset({'A', 'B'}), 10), (frozenset({'C', 'D'}), 15)]

最后,要获得所需结构的结果,您只需执行以下操作:

result = [sorted(e) for e, weight in sorted_uniques]
# result = [['A', 'D'], ['B', 'C'], ['A', 'B'], ['C', 'D']]

1
投票

您可以在frozenset的帮助下将每个边缘表示为set并过滤边缘重复:

G = {"A": [["B",10], ["D",5]], "B": [["A",10], ["C",5]], "C": [["B",5],["D",15]], "D": [["C",15], ["A",5]]}

edges = {(frozenset((k, i)), j) for k, v in G.items()
                                for i, j in v}
[sorted(i) for i, _ in sorted(edges, key=lambda x: x[1])]
# [['B', 'C'], ['A', 'D'], ['A', 'B'], ['C', 'D']]

1
投票

您可以使用itertools.product生成密钥与每个相关子列表的组合。如果您对每个组合的字符串组件进行排序和解包,那么您将获得所需的初始输出。从那里,您可以先按重量值排序整个列表,然后按顶点排序,以获得有序列表。如果使用步长值对该列表进行切片,则可以删除重复项。然后你可以删除权重值来获得最终输出的对列表。

您可以稍微整合下面的步骤,但这会通过您的问题中列出的步骤进行,以便更容易理解。

from itertools import product
from operator import itemgetter

d = {"A": [["B",10], ["D",5]], "B": [["A",10], ["C",5]], "C": [["B",5],["D",15]], "D": [["C",15], ["A",5]]}

combos = [[*sorted([c1, c2]), n] for k, v in d.items() for c1, [c2, n] in product(k, v)]
print(combos)
# [['A', 'B', 10], ['A', 'D', 5], ['A', 'B', 10], ['B', 'C', 5], ['B', 'C', 5], ['C', 'D', 15], ['C', 'D', 15], ['A', 'D', 5]]

ordered = sorted(combos, key=itemgetter(2, 0, 1))[::2]
print(ordered)
# [['A', 'D', 5], ['B', 'C', 5], ['A', 'B', 10], ['C', 'D', 15]]

pairs = [o[:-1] for o in ordered]
print(pairs)
# [['A', 'D'], ['B', 'C'], ['A', 'B'], ['C', 'D']]

编辑(没有进口):

每条评论突出显示在您的解决方案中使用导入的限制,这里是原始版本的修改版本。差异是itertools.product的替换与列表理解,完成相同的事情和用lambda替换operator.itemgetter

d = {"A": [["B",10], ["D",5]], "B": [["A",10], ["C",5]], "C": [["B",5],["D",15]], "D": [["C",15], ["A",5]]}

combos = [[*sorted([k, c]), n] for k, v in d.items() for c, n in v]
print(combos)
# [['A', 'B', 10], ['A', 'D', 5], ['A', 'B', 10], ['B', 'C', 5], ['B', 'C', 5], ['C', 'D', 15], ['C', 'D', 15], ['A', 'D', 5]]

ordered = sorted(combos, key=lambda x: (x[2], x[0], x[1]))[::2]
print(ordered)
# [['A', 'D', 5], ['B', 'C', 5], ['A', 'B', 10], ['C', 'D', 15]]

pairs = [o[:-1] for o in ordered]
print(pairs)
# [['A', 'D'], ['B', 'C'], ['A', 'B'], ['C', 'D']]
© www.soinside.com 2019 - 2024. All rights reserved.