我有一个包含2种节点的图表 - '字母节点' (L)和'数字节点' (N)。我有2个字典,一个显示从L到N的边缘,另一个显示从N到L的边缘。
A = {0:(b,), 1:(c,), 2:(c,), 3:(c,)}
B = {a:(3,), b:(0,), c:(1,2,3)}
键值对c:(1,2,3)
表示从c
到1,2,3
(3条边)有边缘
我想将它们合并到一个字典C
,以便结果是一个新字典:
C = {(0,): (b,), (1, 2, 3): (a, c)}
或
C = {(b,):(0,), (a, c):(1, 2, 3)}
在结果字典中,我希望字母节点和数字节点位于键和值的不同侧。我不在乎哪个是关键或价值,只需要将它们分开。我怎样才能有效地解决这个问题?
澄清:这是一个包含两种类型节点的图形 - 数字节点和字母节点。字典C从字母节点(a,c)说出你可以到达节点(1,2,3),即a-> 3-> c-> 1,a-> 3-> c- > 2因此你可以从a到达1,2,3。即使从a到2或从1到1也没有直接边缘。
答案 0 :(得分:2)
根据你的陈述,我猜你正试图找到图算法。
import itertools
def update_dict(A, result): #update vaules to the same set
for k in A:
result[k] = result.get(k, {k}).union(set(A[k]))
tmp = None
for i in result[k]:
tmp = result.get(k, {k}).union(result.get(i, {i}))
result[k] = tmp
for i in result[k]:
result[i] = result.get(i, {i}).union(result.get(k, {k}))
A = {0:('b',), 1:('c',), 2:('c',), 3:('c',)}
B = {'a':(3,), 'b':(0,), 'c':(1,2,3)}
result = dict()
update_dict(A, result)
update_dict(B, result)
update_dict(A, result) #update to fix bugs
update_dict(B, result)
k = sorted([sorted(list(v)) for v in result.values()])
k = list( k for k, _ in itertools.groupby(k)) #sort and remove dumplicated set
final_result = dict()
for v in k: #merge the result as expected
final_result.update({tuple([i for i in v if isinstance(i, int)]):tuple([i for i in v if not isinstance(i, int)])})
print final_result
#output
{(0,): ('b',), (1, 2, 3): ('a', 'c')}
答案 1 :(得分:0)
所以我不确定这是否是目前最有效的方法,但它确实有效:
A = {0:('b',), 1:('c',), 2:('c',), 3:('c',)}
B = {'a':(3,), 'b':(0,), 'c':(1,2,3)}
# Put B in the same form as A
B_inv = {}
for k, v in B.items():
for i in v:
if B_inv.get(i) is not None:
B_inv[i] = B_inv[i].union(k)
else:
B_inv[i] = set(k)
B_inv = {k: tuple(v) for k, v in B_inv.items()}
AB = set(B_inv.items() + A.items()) # get AB as merged
这将为您提供合并的词典。从这里开始:
new_dict = {}
for a in AB:
for i in a[1]:
if new_dict.get(i) is not None:
new_dict[i] = new_dict[i].union([a[0]])
else:
new_dict[i] = set([a[0]])
# put in tuple form
new_dict = {tuple(k): tuple(v) for k,v in new_dict.items()}
这给了我:
{('a',): (3,), ('b',): (0,), ('c',): (1, 2, 3)}
基本上,我依赖于集合的可变性及其内置的消除重复的功能,试图将每个字典的循环次数保持在最低限度。除非我错过了什么,否则这应该是线性时间。
从这里开始,我需要进行比较,并再次依靠集合来防止我需要对每个元素进行最坏情况的成对比较。
merge_list = []
for k, v in new_dict.items():
matched = False
nodeset = set([k[0]]).union(v)
for i in range(len(merge_list)):
if len(nodeset.intersection(merge_list[i])) != 0:
merge_list[i] = merge_list[i].union(nodeset)
matched = True
# did not find shared edges
if not matched:
merge_list.append(nodeset)
最后,将其转换为带有单个"层的表单"和元组。
C = {}
for item in merge_list:
temp_key = []
temp_val = []
for i in item:
if str(i).isalpha():
temp_key.append(i)
else:
temp_val.append(i)
C[tuple(temp_key)] = tuple(temp_val)
C给了我{('a', 'c'): (1, 3, 2), ('b',): (0,)}
。
答案 2 :(得分:-1)
试试这个:
c = a.copy()
c.update(b)