Reputation: 443
I have a list containing thousands of sets similar to this:
set_list = [a, b, c, d]
each set in the list look something like this:
a = set([1, 2, 3, 4, 5])
b = set([4, 5, 6, 7, 7, 9])
c = set([1, 2, 6, 8, 10, 12, 45])
d = set([11, 3, 23, 3, 4, 44])
I would like to do the set operation: X-(YUZUAUB......etc) for every set in the list, for example, this would look something like this:
after applying this operation on all elements in set_list
the new elements look like this:
a = a.difference(b.union(c, d))
b = b.difference(c.union(a, d))
c = c.difference(d.union(b, a))
d = d.difference(a.union(c, b))
how do i accomplish this?
Upvotes: 5
Views: 3770
Reputation: 500357
One possibility is to make use of the multiset
module to precompute the multiset union of all elements in set_list
, like so:
from multiset import Multiset
union = sum(set_list, Multiset())
set_list = [s - (union - s) for s in set_list]
Here, union - s
computes the Y ∪ Z ∪ A ∪ B...
in your notation.
See Aran-Fey's answer for the same method implemented (more verbosely) using only the standard library.
Upvotes: 3
Reputation: 9863
[value - {item for subset in set_list[0:index] + set_list[index + 1:] for item in subset} for index, value in enumerate(set_list)]
which means:
result = []
for index, value in enumerate(set_list):
union = {
item
for subset in set_list[0:index] + set_list[index + 1:]
for item in subset
}
result.append(value - union)
print(result)
Outputs:
[set(), {9, 7}, {8, 10, 12, 45}, {11, 44, 23}]
Upvotes: 1
Reputation: 43166
This is a re-implementation of NPE's answer using collections.Counter
from the standard library:
from collections import Counter
def mutual_difference(set_list):
# create a multiset out of the union of all sets
union = Counter()
for s in set_list:
union.update(s)
new_set_list = []
for s in set_list:
# subtract s from the union and discard 0-count elements
union.subtract(s)
union += {}
# take the difference
new_set_list.append(s.difference(union))
# add s to the union again
union.update(s)
return new_set_list
Example:
>>> mutual_difference([{1,2}, {2,3}, {1,4,5}])
[set(), {3}, {4, 5}]
Upvotes: 1
Reputation: 1343
If I'm understanding correctly, you want the difference for each set and the union of the rest of the sets. I would use a loop and functools.reduce
and operator.or_
:
Setup
import functools
import operator
a = set([1, 2, 3, 4, 5])
b = set([4, 5, 6, 7, 7, 9])
c = set([1, 2, 6, 8, 10, 12, 45])
d = set([11, 3, 23, 3, 4, 44])
set_list = [a, b, c, d]
Loop and save results
# I don't know what you want to do with the results so
# I'll save them in a list...
results = []
for i in set_list:
list_copy = list(set_list)
list_copy.remove(i)
r = i - functools.reduce(operator.or_, list_copy)
results.append(r)
print(results)
# prints [set(), {9, 7}, {8, 10, 12, 45}, {11, 44, 23}]
Upvotes: 1