-3

I have a list of sets [{'1'}, {'2','8'}, {'3','9', '1'}]. I want to loop through this list and find the union of all of these sets. I have done the following but my set maintains empty:

my_set = set()
for i in [{'1'}, {'2','8'}, {'3','9'}]:
  print(i)
  my_set.union(set(i))
  print(my_set)
print(my_set)

The output is the following:

{'1'}
set()
{'8', '2'}
set()
{'9', '3'}
set()
set()

Note: Please fix my loop and do not propose a shortcut that does not use a loop and union.

Saeed
  • 598
  • 10
  • 19
  • The union functions returns a set, just do `my_set = my_set.union(set(i))` – Dani Mesejo Sep 13 '21 at 21:24
  • what is the expected final result? – balderman Sep 13 '21 at 21:24
  • 1
    "Please fix my loop and do not propose a shortcut that does not use a loop and union": why? – 9769953 Sep 13 '21 at 21:30
  • 1
    `my_set.union(set(i))` does not work in-place, it returns a *new set*. You should use either `.update` for this or the augmented union operator: `myset |= i` (note, using `set(i)` is **pointless and inefficient**). You shouldn't do `my_set = my_set.union(i)` because this will be *inefficient in a loop*. – juanpa.arrivillaga Sep 13 '21 at 21:59
  • 1
    isn't this just `my_set = {a for s in [{'1'}, {'2','8'}, {'3','9'}] for a in s}`? – Samwise Sep 13 '21 at 22:15
  • try my_set=set() for i in [{'1'}, {'2','8'}, {'3','9'}]: my_set=my_set.union(i) print(my_set) – Golden Lion Sep 28 '21 at 21:47

4 Answers4

4

The union method returns a new set, but it doesn't change the current set(s). You need to (re)assign the result to my_set:

my_set = set()
for i in [{'1'}, {'2','8'}, {'3','9'}]:
    my_set = my_set.union(i)
print(my_set)

Note that i is a set already, so no need to call set(i)

If you want an in-place change of my_set, use the following:

my_set = set()
for i in [{'1'}, {'2','8'}, {'3','9'}]:
    my_set.update(i)

or

my_set = set()
for i in [{'1'}, {'2','8'}, {'3','9'}]:
    my_set |= i

But union() accepts multiple sets as argument, so you can do the following (start with an empty set):

my_set = set().union({'1'}, {'2','8'}, {'3','9'})

No need for a loop.

You can also use set.union(...) as a class method (from balderman's comment below) instead of set().union(...). And if your list (or tuple) of sets happens to be a variable, the following works:

sets = [{'1'}, {'2','8'}, {'3','9'}]
my_set = set.union(*sets)
9769953
  • 10,344
  • 3
  • 26
  • 37
  • 1
    no need for creating `set` instance. `u = set.union({'1'}, {'2','8'}, {'3','9', '1'})` is enough ` – balderman Sep 13 '21 at 21:35
  • @balderman Thanks, added. I hadn't come across the class method use mentioned in the documentation; it definitely makes sense though. – 9769953 Sep 14 '21 at 04:47
1

Python's set method X.union(Y) returns a new set that is the union of X and Y. You're looking for my_set.update(set(i)).

You could, of course, write that as my_set = my_set.union(set(i)), but that's probably slower since it has different semantics (.update() uses the inplace addition method, while union will construct an additional copy.)

kcsquared
  • 5,244
  • 1
  • 11
  • 36
0

You have to reassign value returned by union

my_set = set()
for i in [{'1'}, {'2','8'}, {'3','9'}]:
  print(i)
  my_set = my_set.union(set(i))
  print(my_set)
print(my_set)
Will Da Silva
  • 6,386
  • 2
  • 27
  • 52
jetpack_guy
  • 350
  • 2
  • 9
  • 12
0

Use my_set.update(i) instead of union. BTW you don't need the set(i) since i is already a set. It would also work without casting to set if i was a list.

given that i is a set, you could also write it as:

my_set |= i

or even do it all in one line:

my_set = set().union(*[{'1'}, {'2','8'}, {'3','9', '1'}]) 
Alain T.
  • 40,517
  • 4
  • 31
  • 51