2

I cant seem to figure out how to write the following into a one line of code, using set comprehension. If its not possible is there a faster way to do what I am trying to do here? Basically just getting all the values of a dictionary into a set. Some values can be an empty set. A simple example is below

d = {1:set(),2:{1,2,3},3:{4}}

t = set()

for k, v in d.items():
   if len(v) > 0:
      t.update(v)

print(t)

output

{1,2,3,4}
user1179317
  • 2,693
  • 3
  • 34
  • 62

3 Answers3

7

Easiest is probably:

>>> set.union(*d.values())
{1, 2, 3, 4}

There's no need to special-case an empty set in the values. Folding an empty set into the union makes no difference to the result, and checking for the length in advance in Python code is slower than just letting set.union() figure it out.

WITH A SET COMPREHENSION

You can do it with a set comprehension too, but I expect this way would be significantly slower (although I haven't timed it):

>>> {x for oneset in d.values() for x in oneset}
{1, 2, 3, 4}
Tim Peters
  • 67,464
  • 13
  • 126
  • 132
  • As i mentioned above, I did try set.union before but wasnt getting the answer. Apparently i was missing the * in it thats why it wasnt working. Thanks. What does the * doing that it doesnt work without it? – user1179317 Jan 05 '18 at 17:32
  • 3
    @user1179317 See [Unpacking Argument Lists](https://docs.python.org/3/tutorial/controlflow.html#unpacking-argument-lists) – PM 2Ring Jan 05 '18 at 17:38
3

As an alternative to the union thing, you could use chain.from_iterable:

from itertools import chain

d = {1:set(),2:{1,2,3},3:{4}}
set(chain.from_iterable(d.values()))
>>> {1, 2, 3, 4}
jdehesa
  • 58,456
  • 7
  • 77
  • 121
1

Both Tim Peters's and jdehesa's answers are faster than using a set comprehension because they avoid the explicit double for loop running at Python speed. But here's how to do it with a set comprehension:

d = {1:set(), 2:{1,2,3}, 3:{4}}
t = {v for u in d.values() for v in u}
print(t)

output

{1, 2, 3, 4}
PM 2Ring
  • 54,345
  • 6
  • 82
  • 182