Conditional Conjunction of two Iterables

188 Views Asked by At

I have an odd situation that is causing me confusion (and errors.) I've renamed the variables to be more clear, but the problem is real. I have two iterables that I need to combine. The combination should be a conjunction without repetition. However, if an element is the "opposite" of another, neither should exist in the final set.

Conceptual Example: (a, b, c) COMBINE (b, c', d) -> (a, b, d) # Let c be opposite of c'

Here is my current implementation that fails in part because I am trying to modify the size of a set while iterating over it:

# atom_list and atom_set are distinct not only in their type but also their contents.
for atom in atom_list:
    should_add = True
    for other_atom in atom_set:
        if atom.is_opposite(other_atom):
            # Todo: cause anti-matter/matter explosion!!
            atom_set.remove(other_atom)
            should_add = False
    if should_add:
        atom_set.add(atom)

Are there any thoughts as to how to make this cleaner (and work without modifying the set that I'm iterating over)? I feel like a good solution to this problem will involve more than just copying the set at first...

2

There are 2 best solutions below

6
On BEST ANSWER

As you say modifying the iterable while iterating over it is not a good idea. Why not create another set?

combined_set = set()
for atom in atom_list:
    if atom.opposite() not in atom_set:
        combined_set.add(atom)

atom_list_set = set(atom_list)
for atom in atom_set:
    if atom not in atom_list_set:
        combined_set.add(atom)

This assumes that an opposite() method exists which returns the opposite of an atom. The second for loop handles atoms which are in atom_set but not in atom_list.

4
On

Quick 'dirty' solution:

s1 = set([1, 2, 3])
s2 = set([4, -2, 5])
res = [x for x in s1 | s2 if -x not in s1 and -x not in s2]

2 and -2 are opposite elements which we exclude. It gives [1, 3, 4, 5].