2

I have

x = {'a':set([1]) , 'b':set([2]), 'c':set([3]) }

It is guaranteed that there is only one element in the set. I need to convert this to

{'a': 1, 'c': 3, 'b': 2}

Following works:

x1 = {k:x[k].pop() for k in x.keys()}  OR
x1 = {k:next(iter(x[k])) for k in x.keys()}

but I am not liking it as pop() here is modifying the original collection. I need help on following.

  • How can I use unpacking as mentioned here within comprehension.
  • Is there any way, I can use functools.reduce for this.
  • What can be a better or Pythonic way of doing this overall?
martineau
  • 119,623
  • 25
  • 170
  • 301
ViFI
  • 971
  • 1
  • 11
  • 27

2 Answers2

6

If you want to do this with an unpacking, that'd be

{k: item for k, [item] in x.iteritems()}
user2357112
  • 260,549
  • 28
  • 431
  • 505
  • This will produce an `AttributeError` within `Python 3.5.2`. – Chiheb Nexus May 24 '17 at 22:18
  • 2
    @ChihebNexus: Indeed it will, but the question is tagged 2.7. – user2357112 May 24 '17 at 22:19
  • Thanks for this. That's what I wanted. Just to mention for other, unpacking also performs the validation that there is only one element in set which is the case here. unpacking on elements with more than one elements will give an error. – ViFI May 24 '17 at 23:23
  • `{k: item for k, [item] in x.items()}` would be the way to do it someone is looking for the version compatible with Python 2 as well as 3. `items` is inefficient in Python 2 but for small lists shouldn't matter much. – ViFI May 24 '17 at 23:27
3

In my opinion, the most readable option would be to use next and iter. Unpacking might also not be of much use since it is more of an assignment operation. (See user2357112's answer)

How about simply:

>>> {k: next(iter(v)) for k, v in x.items()}
{'a': 1, 'c': 3, 'b': 2}
UltraInstinct
  • 43,308
  • 12
  • 81
  • 104