之前使用過一種方法實現求集合間的並集,參考文章:https://www.cnblogs.com/mrlayfolk/p/12373532.html,這次使用另外一種方法實現,這種方法效率更高。
目的:
求多個集合之前的並集,例如:現有四個集合C1 = {11, 22, 13, 14}、C2 = {11, 32, 23, 14, 35}、C3 = {11, 22, 38}、C4 = {11, 22, 33, 14, 55, 66},則它們之間的並集應該為:
C1 & C2 & C3 = {11}、C1 & C2 & C4 = {14}、C1 & C3 & C4 = {22}。如下圖所示:

實現步驟:
以上述的四個集合為例進行說明:C1 = {11, 22, 13, 14}、C2 = {11, 32, 23, 14, 35}、C3 = {11, 22, 38}、C4 = {11, 22, 33, 14, 55, 66}。
(1)首先找到成員數最多的集合,為C4 = {11, 22, 33, 14, 55, 66},將C4的每個成員依次和各個集合的成員進行比較,判斷這個成員是否再其它集合中存在。
(2)經過比較我們可以得到:11∈C1、C2、C3、C4; 22∈C1、C3、C4; 14∈C1、C2、C4; 33、55、66∈C4。
(3)接着,將除C4以外,剩余集合的剩余成員找出來,C1 = {13},C2 = {32、23、35},C3 = {38}。
(4)找出成員數最多的集合,這里是C2,將C2的各個成員和其它集合進行比較。得到:32、23、35∈C2;
(5)接着只剩下C1和C3了,兩個集合的成員數一樣,例如使用C1的成員和C3進行比較之后,得到:13∈C1,38∈C3。
通過上述步驟,我們最終得到:C1 & C2 & C3 = {11}、C1 & C2 & C4 = {14}、C1 & C3 & C4 = {22}。
當然,也可以先找出成員數最少的集合,逐個使用這個集合的成員與其它集合的成員進行對比,也能夠得到各個集合之間的交集。
實現代碼:
下面python代碼實現的是每次使用成員數最少的集合和其它集合的成員進行對比的情況:
1 # decoding: utf-8 2 3 import os 4 import sys 5 import xlrd 6 import logging 7 import csv 8 import numpy as np 9 10 # 設置logging.basicConfig()方法的參數和配置logging.basicConfig函數 11 FORMAT = '[%(funcName)s: %(lineno)d]: %(message)s' 12 LEVEL = logging.INFO 13 logging.basicConfig(level = LEVEL, format=FORMAT) 14 15 16 def func(content): 17 all_dict = {} 18 for d in content: 19 for k in d.keys(): 20 tmp_value = d[k] 21 if k in all_dict.keys(): 22 tmp_values = all_dict[k] 23 # 更新成員數 24 for i in range(len(tmp_value)): 25 if tmp_value[i] not in tmp_values: 26 tmp_values.append(tmp_value[i]) 27 all_dict[k] = tmp_values 28 29 if k not in all_dict.keys(): 30 # 這里需要處理一種情況:如13: [0, 0],某個字典的值有重復的元素。 31 tmp_values = [] 32 for i in range(len(tmp_value)): 33 tmp = tmp_value[i] 34 if tmp in tmp_values: 35 continue 36 tmp_values.append(tmp) 37 all_dict[k] = tmp_values 38 39 return all_dict 40 41 42 # get union sets from collections 43 def get_unions(content): 44 c_mems_list = [] 45 for c in content: 46 c_mems_list.append(len(c)) 47 # print (c_mems_list) 48 49 mems_list_index = np.argsort(c_mems_list) 50 # print (mems_list_index) 51 52 # 取成員數最小的集合的成員依次和其它集合進行比較 53 all_index_list = [] 54 for c_index in mems_list_index: 55 min_c = content[c_index] #成員數最小的集合 56 elem_index = {} # 存放成員所在集合的索引,格式如下:[elem, index] 57 for elem in min_c: # 判斷成員數最小的集合的各個成員是否在其它集合中存在 58 index_tmp = [] 59 index_tmp.append(c_index) #首先存放成員數最小集合的索引 60 for other_index in mems_list_index[c_index+1: ]: # 開始判斷本成員在其它集合中是否存在 61 if elem in content[other_index]: #若存在,加入到成員所在集合的索引中去 62 index_tmp.append(other_index) 63 elem_index[elem] = index_tmp 64 all_index_list.append(elem_index) 65 66 # print (all_index_list) 67 all_dict = func(all_index_list) #將重復的索引刪除掉 68 69 return all_dict 70 71 72 if __name__ == "__main__": 73 74 # original data 75 C0 = {11, 22, 13, 14} 76 C1 = {11, 32, 23, 14, 35} 77 C2 = {11, 22, 38} 78 C3 = {11, 22, 33, 14, 55, 66} 79 80 print ('############## enter main ##############') 81 res = get_unions([C0, C1, C2, C3]) 82 for key in res: 83 print (key, ':', res[key]) 84 print ('############## end main ##############')
輸出結果如下:
1 ############## enter main ############## 2 38 : [2] 3 11 : [2, 3, 0, 1] 4 22 : [2, 3, 0] 5 13 : [0] 6 14 : [0, 1, 3] 7 32 : [1] 8 35 : [1] 9 23 : [1] 10 33 : [3] 11 66 : [3] 12 55 : [3] 13 ############## end main ##############
下面我們換一組數據進行測試:
1 if __name__ == "__main__": 2 3 # original data 4 C0 = {11, 22, 13, 14, 15} 5 C1 = {11, 22, 23, 14, 35} 6 C2 = {11, 22, 38, 15, 66} 7 C3 = {11, 22, 33, 14, 55, 66} 8 C4 = {22, 33, 15, 89, 33} 9 10 print ('############## enter main ##############') 11 res = get_unions([C0, C1, C2, C3, C4]) 12 for key in res: 13 print (key, ':', res[key]) 14 print ('############## end main ##############')
輸出結果如下:
1 ############## enter main ############## 2 89 : [4] 3 33 : [4, 3] 4 22 : [4, 0, 1, 2, 3] 5 15 : [4, 0, 2] 6 11 : [0, 1, 2, 3] 7 13 : [0] 8 14 : [0, 1, 3] 9 35 : [1] 10 23 : [1] 11 66 : [2, 3] 12 38 : [2] 13 55 : [3] 14 ############## end main ##############
可以看出,輸出的結果和預期的一致。
