我试图在python中找到两个sets
之间的交集。但是,一旦找到,我需要union
两个集合并再次在dictionary
上迭代,直到没有进一步的变化。
类似的东西:
dict_={'a': {1,3,4}, 'b': {0,5,4}, 'c': {0,6,5},'e':{7,9}}
我需要什么:
result={'abc':{1,3,4,0,5,4,0,6,5}, 'e':{7,9}}
这是我到目前为止做了什么:
dict_={'a': {1,3,4}, 'b': {0,5,4}, 'c': {0,6,5},'e':{7,9}}
flag=True
while flag:
done=False
for key in list(dict_):
if done: ## to break outer loop
del dict_[remove1]
del dict_[remove2]
break
for newKey in list(dict_):
if key==newKey:
continue
if len(set.intersection(dict_[key],dict_[newKey]))>0:
added_key=str(key)+str(newKey)
dict_[added_key]=set.union(dict_[key],dict_[newKey])
remove1=key
remove2=newKey
done=True
break ## to break inner loop
flag=False ## Here is the problem. I do not know what to do
此代码的结果:
dict_
#{'ab': {0, 1, 3, 4, 5}, 'c': {0, 5, 6}, 'e': {7, 9}}
答案 0 :(得分:1)
正如有人在评论中指出的那样,您所需的输出设置无效。假设你想加入密钥并联合值集,直到它们有任何共同点,你可以这样做:
d ={'a': {1,3,4}, 'b': {0,5,4}, 'c': {0,6,5},'e':{7,9}}
flag = True
while (flag):
keys = list(d.keys())
outer_break = False
for i in range(len(keys)-1):
inner_break = False
for j in range(i+1, len(keys)):
if len(set.intersection(d[keys[i]], d[keys[j]])) > 0:
d[keys[i] + keys[j]] = set.union(d[keys[i]], d[keys[j]])
del d[keys[i]]
del d[keys[j]]
inner_break = True
break
if inner_break:
outer_break = True
break
if not outer_break:
flag = False
print (d)
# {'e': {9, 7}, 'cab': {0, 1, 3, 4, 5, 6}}
您也可以使用这样的递归函数执行此操作:
dd ={'a': {1,3,4}, 'b': {0,5,4}, 'c': {0,6,5},'e':{7,9}}
def reduce_dict(d):
keys = list(d.keys())
for i in range(len(keys)-1):
for j in range(i+1, len(keys)):
if len(set.intersection(d[keys[i]], d[keys[j]])) > 0:
d[keys[i] + keys[j]] = set.union(d[keys[i]], d[keys[j]])
del d[keys[i]]
del d[keys[j]]
return reduce_dict(d)
return d
dd = reduce_dict(dd)
print(dd)
# {'e': {9, 7}, 'cab': {0, 1, 3, 4, 5, 6}}
答案 1 :(得分:1)
我建议使用itertools.combinations来查看所有可能的唯一键组合,您可以避免使用这么多标志,而是以这种方式使用看到的set():
from itertools import combinations
dict_={'a': {1,3,4}, 'b': {0,5,4}, 'c': {0,6,5},'e':{7,9}}
for i in range(2,len(dict_)+1): # For length of dict from 2
# Initialize the "seen" list
seen_keys = set()
for combination in list(combinations(dict_, 2)): # Get possible key combinations of 2
keys_in_combination = [dict_[x] for x in combination] # And their values in a list
if len(set.intersection(*keys_in_combination)): # * Expands the list into the arguments
# Make key names alphabetical with no duplicate letters.
added_key = "".join(sorted(set(x for y in combination for x in str(y))))
# Join 2 sets under new key
dict_[added_key] = set.union(*keys_in_combination)
for seen_key in combination:
# create a seen list (for the deletion below)
seen_keys.add(seen_key)
# Delete the keys which have been joined to others
for key in dict_.copy():
if len(key) < i and key in seen_keys:
del dict_[key]
print(dict_)
结果:
{'abc': set([0, 1, 3, 4, 5, 6]), 'e': set([9, 7])}
此方法也适用于组合可能长于&#34; abc&#34;
的词组。答案 2 :(得分:0)
一种非常优化的方法是使用一系列的项目 并循环遍历列表,然后递归更新项目 有任何交集。
def find_intersection(m_list):
for i, (key_1, v) in enumerate(m_list) :
for j, (key_2, k) in enumerate(m_list[i+1:],i+1):
if v & k:
m_list[i] = key_1 + key_2, v.union(m_list.pop(j)[1])
return find_intersection(m_list)
return m_list
演示:
In [10]: find_intersection(list(mydict.items()))
Out[10]: [('abc', {0, 1, 3, 4, 5, 6}), ('e', {7, 9})]