Is there a more compact way to convert a sequence (key, value) of tuples to a {key: [value, ..], ..} dict?

I have a sequence of itemList

formatted tuples (key, value)

and I want to convert the items in this list dict

to formatted {key : [value, ..], ..}

. The specific value key

can appear itemList

multiple times with the same or new value

, and I want to write those values ​​as well (so just using dict(itemList)

doesn't work).

I am using Python2.7.9

and looking for ways to miniaturize this code:

newDict = dict()
for k,v in itemList:  # itemList contains the tuples described above.
    if k in newDict:
        newDict[k].append(v)
    else:
        newDict[k] = [v]

      

I've tried using map()

and list-comprehensions

in combination with newDict.update(..)

, but none of them worked out as intended.

I've looked at this similar question , but the format of my inputs and the desired output is significantly different.

(For those wondering, "Why would you want to change this perfectly acceptable code?" I'm interested in finding alternative ways to use Python's built-in modules and modules more as an academic exercise rather than purposefully avoiding anything functional and straightforward.)

+3


source to share


2 answers


You can use dict.setdefault

to shorten your code like

newDict = {}
for k, v in itemList:
    newDict.setdefault(k, []).append(v)

      

setdefault

will look for a key in the dictionary, if not found it will assign a second parameter to it and return it.

If the key is in the dictionary, it will simply return the corresponding value.




Alternatively you can use collections.defaultdict

for example

from collections import defaultdict

result = defaultdict(list)
for k, v in itemList:
    result[k].append(v)

      

This is similar to the approach setdefault

. If the key is not found in the dictionary, then the function passed to the constructor defaultdict

is called to create a new value.

+4


source


This single line can replace the posted code, but is significantly more difficult to read. This is probably not very fast either, as it has to go through several times itemList

.



newDict = dict((k, [_v for _k,_v in itemList if _k == k]) for k in set(i[0] for i in itemList))

0


source







All Articles