lifebalance
lifebalance

Reputation: 1927

Code to find unique elements among lists / sets

Shaded area required

The above shaded area, according to Wolfram is supposed to represent:

 A XOR B XOR C XOR (A AND B AND C)

How to translate this into python code? The code must closely correlate to the set operations as provided in the above expression, at least that is the preference. The code must be generic enough to handle more more than 3 lists as well.

UPDATE: Seems like Wolfram is throwing up an erroneous venn diagram? Also, what we actually want is

(A XOR B XOR C) - (A AND B AND C)

and I am not able to represent that in Wolfram.

Upvotes: 3

Views: 1988

Answers (2)

wpedrak
wpedrak

Reputation: 687

Python supports sets (more about sets). For three lists it will be:

A = [1, 2, 3, 4]
B = [2, 3, 5, 6]
C = [3, 4, 5, 7]
As = set(A)
Bs = set(B)
Cs = set(C)

print((As ^ Bs ^ Cs) ^ (As & Bs & Cs))

For list of lists (this is wrong - all it does is XORing all sets, ANDing all sets and than XORing this two results - correct solution below):

import functools

def do_xor(s1, s2):
    return s1 ^ s2

def do_and(s1, s2):
    return s1 & s2

def do_task(list_of_lists):
    list_of_sets = list(map(set, list_of_lists))
    xors = functools.reduce(do_xor, list_of_sets)
    ands = functools.reduce(do_and, list_of_sets)
    return xors ^ ands

A = [1, 2, 3, 4]
B = [2, 3, 5, 6]
C = [3, 4, 5, 7]
D=[A, B, C]
print(do_task(D))

Correct solution:

import functools 

def do_or(s1, s2):
    return s1 | s2

def do_task2(list_of_lists):
    list_of_sets = list(map(set, list_of_lists))
    list_of_intersects = [X & Y for X in list_of_sets for Y in list_of_sets if X is not Y]
    intersects = functools.reduce(do_or, list_of_intersects)
    ors = functools.reduce(do_or, list_of_sets)
    return ors - intersects

lol33 = [
    [1, 2], 
    [3, 2], 
    [3], 
    [3, 2, 4]
    ]

print(do_task2(lol33)) # {1, 4}

Upvotes: 4

jpp
jpp

Reputation: 164623

You can use operations & [intersection] and | [union] for your purpose. Data from @WPedrak.

A = {1, 2, 3, 4}
B = {2, 3, 5, 6}
C = {3, 4, 5, 7}

lst = [A, B, C]

result = (A | B | C) - ((A & B) | (A & C) | (B & C) | (A & B & C))

# {1, 6, 7}

Explanation

We take the union of all elements and subtract all intersections. See @WPedrak's solution for general case.

Upvotes: 2

Related Questions