繁体   English   中英

不仅是多组的交集,还有联合和更新

[英]Not only the intersection of multiple sets, but also union and update

我试图在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}}

正如有人在评论中指出的那样,您所需的输出设置无效。 假设你想加入密钥并联合值集,直到它们有任何共同点,你可以这样做:

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}} 

我建议使用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])}

此方法也适用于组合可能长于“abc”的dicts。

一种非常优化的方法是使用一个dictioanry项列表并循环遍历列表,然后如果它们有任何交集,则递归地更新项。

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})]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM