Code to find unique elements among lists / sets
Asked Answered
R

2

3

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.

Reinert answered 5/3, 2018 at 20:8 Comment(0)
G
4

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}
Gusset answered 5/3, 2018 at 20:21 Comment(9)
But what I have n lists?Reinert
If lol1 = [ [1, 2], [3, 2] ], then do_task(lol1) returns {1, 2, 3}. How come?Reinert
If lol33 = [ [1, 2], [3, 2], [3], [3, 2, 4] ] then do_task(lol3) returns {1, 2, 3, 4}. This is incorrect, right?Reinert
I am very intrigued as to why this doesn't work. Use this to further probe where the problem might be...repl.it/@kgashok/MotionlessUnderstatedLinuxpcReinert
It was my fail I didn't read title of the question... solution: repl.it/repls/InnocentSteelblueGlobalarrays I'll edit answer in a minute.Gusset
Patter (provided in question) of solving this problem is simply wrong ;) Example of Wolfram on two sets wolframalpha.com/input/?i=A+XOR+B+XOR+(A+AND+B)Gusset
Thanks for the corrected solution. If the Venn diagram is wrong, then what is the correct one and what should be the correct expression?Reinert
Venn diagram is just way to draw relations between sets, not method of computing unique elements, so it can not "be wrong". XORing and ANDing all the sets (in a way mentioned in question) as a method to archive it is wrong.Gusset
Thanks, you can also write do_or as lambda function: intersects = functools.reduce(lambda s1,s2: s1|s2, i)Adama
N
2

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.

Nitrochloroform answered 5/3, 2018 at 22:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.