1

I have a dictionary like so:

myDict = {'items':
            [{'names': [{'longName1', 'shortName1'},
                      {'shortName2', 'longName2'}]},
            {'names': [{'longName3', 'shortName3'},
                      {'shortName4', 'longName4'}]}]}

Attempting to get the keys (i.e. shortName) in a set Pythonically. I have the following statement, but it's complaining that i isn't defined. What am I doing wrong?

shortNames = set().union(*(j.values() for j in i["names"] for i in myDict["items"]))

Expected result:

set(['shortName1', 'shortName2', 'shortName3', 'shortName4'])
Karioki
  • 646
  • 6
  • 18
ILostMySpoon
  • 2,399
  • 2
  • 19
  • 25

3 Answers3

2

You are accessing i["names"] before i is defined by i in myDict["items"].

dacx
  • 824
  • 1
  • 9
  • 18
1

You have to swap the for loops:

set().union(*[j for i in myDict["items"] for j in i["names"]])
Mykola Zotko
  • 15,583
  • 3
  • 71
  • 73
0

See, it is not advisable to chain list comprehensions just for the sake of brevity. Since you are asking, one way would be:

>>> from itertools import chain
>>> {j for j in (chain.from_iterable(sum([i['names'] for i in myDict['items']],[]))) if j.startswith('short')}

{'shortName1', 'shortName2', 'shortName3', 'shortName4'}

Your method could not work:

  1. As dacx mentioned.

  2. j.values() would not give you shortNames as those are inside sets not dicts, and sets do not have .values() method.


OR:

>>> {j for j in set().union(*(set().union(*i['names']) for i in myDict['items'])) if j.startswith('short')}
{'shortName1', 'shortName2', 'shortName3', 'shortName4'}
Sayandip Dutta
  • 15,602
  • 4
  • 23
  • 52