如果给我一个字典来表示一个图形,其中顶点是键,值是列表,其条目既包含相邻顶点又包含两个顶点之间的权重,那么如何以递增顺序返回边列表没有重复?例如,可能会给我以下字典...
{“ 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']]
答案 0 :(得分:3)
因此,您有一个将图形表示为邻接列表的字典,并且您想要将该邻接列表转换为边列表。
您可以通过嵌套列表理解来做到这一点:
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)]
然后,您可以通过转换为字典来消除重复的边,请注意,如果重复的边具有权重冲突,则将任意选择其中一个权重:
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_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 :(得分: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']]
答案 2 :(得分:1)
您可以将每个边缘表示为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']]
过滤边缘重复项:
Number.isInteger(month) && month >= 1 && month <= 12