簡體   English   中英

查找四個集合相交的所有線段成員(阿拉維恩圖)

[英]Finding all segments members of four sets intersections (ala Venn diagram)

我有四組數據:

A=range(10,20) 
B=range(5,17) 
C=range(15,25) 
D=range(18,30)
sets = [A, B, C, D]

我想要做的是獲取相交的內容,可以將其視為此處獲得維恩圖的所有部分(這是完整的情況):

在此處輸入圖片說明

在上面的示例中,分區的填充如下:

()  ----> set()
('A',)  ----> set()
('B',)  ----> {8, 9, 5, 6, 7}
('C',)  ----> set()
('D',)  ----> {25, 26, 27, 28, 29}
('A', 'B')  ----> {10, 11, 12, 13, 14}
('A', 'C')  ----> {17}
('A', 'D')  ----> set()
('B', 'C')  ----> set()
('B', 'D')  ----> set()
('C', 'D')  ----> {24, 20, 21, 22, 23}
('A', 'B', 'C')     ----> {16, 15}
('A', 'B', 'D')     ----> set()
('A', 'C', 'D')     ----> {18, 19}
('B', 'C', 'D')     ----> set()
('A', 'B', 'C', 'D')    ----> set()

這些是預期的答案。

我陷入下面的代碼,只能找到所有給定集中必須存在的交集:

# only gives ACD members
test = [tuple([A[0],A[-1]]), tuple([C[0],C[-1]]), tuple([D[0],D[-1]])]
starts, ends = zip(*test)
result = range(max(starts), min(ends) + 1)
# Gives 18,19

怎么做呢? 請注意,我對繪制圖表不感興趣。 我關心的是讓每個細分市場的成員。

我在此處通過博客發布了有關此類問題的解決方案: http : //paddy3118.blogspot.de/2013/07/set-divisionspartitions.html

您可能需要將x..y語法擴展為整數集,但是如果該輸出形式對您有用,那么您可能希望將輸出與此類函數進行接口: http : //rosettacode.org/wiki/Range_extraction

PS那是一個漂亮的維恩圖。

最好使用具有線性運算復雜度(以及輸出的長度)而不是指數的掃描線算法。

A=range(10,20) 
B=range(5,17) 
C=range(15,25) 
D=range(18,30)
sets = [A, B, C, D]
import string
events = []
for letter, set_ in zip(string.ascii_uppercase, sets):
    events.append((set_.start, True, letter))
    events.append((set_.stop, False, letter))
events.sort()
intersection = set()
intersections = []
last_t = None
for t, insert, letter in events:
    if t != last_t and intersection:
        intersections.append((''.join(sorted(intersection)), range(last_t, t))) 
    last_t = t
    if insert:
        intersection.add(letter)
    else:
        intersection.remove(letter)
print(intersections)
import itertools

def powerset(iterable):
    "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
    s = list(iterable)
    return itertools.chain.from_iterable(itertools.combinations(s, r) for r in range(len(s)+1))

A = set(range(10,20)) 
B = set(range(5,17)) 
C = set(range(15,25)) 
D = set(range(18,30))

titles = (partition for partition in powerset(['A', 'B', 'C', 'D']))
source = (partition for partition in powerset([A, B, C, D]))

for elt in (zip(titles, source)):
    try:
        res = elt[1][0]
        for el in elt[1]:
            res.intersection(el)
    except IndexError:
        pass
    print(elt[0], ' = ', res)

輸出=每組之間的交集

()  =  {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29}
('A',)  =  {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}
('B',)  =  {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
('C',)  =  {15, 16, 17, 18, 19, 20, 21, 22, 23, 24}
('D',)  =  {18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29}
('A', 'B')  =  {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}
('A', 'C')  =  {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}
('A', 'D')  =  {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}
('B', 'C')  =  {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
('B', 'D')  =  {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
('C', 'D')  =  {15, 16, 17, 18, 19, 20, 21, 22, 23, 24}
('A', 'B', 'C')  =  {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}
('A', 'B', 'D')  =  {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}
('A', 'C', 'D')  =  {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}
('B', 'C', 'D')  =  {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
('A', 'B', 'C', 'D')  =  {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}

它是這樣的:輸出是專門屬於每個分區的一組元素。 它適用於任意數量的集。

import itertools

def intersect(d):
    """
    d is an iterable collection of sets or frozensets
    returns the intersection of the sets in d"
    """
    res = set()
    try:
        res = set(d[0])
    except IndexError:
        pass
    for elt in d:
        elt = set(elt)
        res = res.intersection(elt)
    return res

A = frozenset(range(10,20))
B = frozenset(range(5,17))
C = frozenset(range(15,25))
D = frozenset(range(18,30))

titles = ('A','B','C','D')
data = (A, B, C, D)

dataset = set(data)
titles_comb, data_comb = [], []

for n in range(len(data)+1):
    titles_comb.append(list(itertools.combinations(titles, n)))
    data_comb.append(list(itertools.combinations(data, n)))

for title, dat in zip(titles_comb, data_comb):
    for t, d in zip(title, dat):
        #intersect(d) = elements in the intersection of the sets (what we want, but has overlap)
        #complement = sets from data that were not used in intersect(d) (the overlap we want to discard)
        result = intersect(d)
        complement = dataset.difference(set(d))
        comp = set()
        for elt in complement:
            for e in elt:
                comp.add(e)

        print(t, "\t---->", result.difference(comp))

輸出=每個分區的內容(不包括所有其他分區)

()  ----> set()
('A',)  ----> set()
('B',)  ----> {8, 9, 5, 6, 7}
('C',)  ----> set()
('D',)  ----> {25, 26, 27, 28, 29}
('A', 'B')  ----> {10, 11, 12, 13, 14}
('A', 'C')  ----> {17}
('A', 'D')  ----> set()
('B', 'C')  ----> set()
('B', 'D')  ----> set()
('C', 'D')  ----> {24, 20, 21, 22, 23}
('A', 'B', 'C')     ----> {16, 15}
('A', 'B', 'D')     ----> set()
('A', 'C', 'D')     ----> {18, 19}
('B', 'C', 'D')     ----> set()
('A', 'B', 'C', 'D')    ----> set()

您是否嘗試過使用python

A = set(range(10,20))
B = set(range(5,17))
C = set(range(15,25))
D = set(range(18,30))

A.intersection(B).intersection(C)
set([15, 16])

A.intersection(B)
set([10, 11, 12, 13, 14, 15, 16])

A.intersection(C).intersection(D)
set([18, 19])

A.intersection(B).intersection(C).intersection(D)
set()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM