Search code examples
pythonlistcollectionsreversedefaultdict

What is the pythonic way to reverse a defaultdict(list)?


What is the pythonic way to reverse a defaultdict(list)?

I could iterating through the defaultdict and creating a new defaultdict. Is there any other way? Is this pythonic:

>>> from collections import defaultdict
>>> x = defaultdict(list)
>>> y = [[1,2,3,4],[3,4,5,6]]
>>> z= ['a','b']
>>> for i,j in zip(y,z):
...     x[j] = i
... 
>>> x
defaultdict(<type 'list'>, {'a': [1, 2, 3, 4], 'b': [3, 4, 5, 6]})
>>> x2 = defaultdict(list)
>>> for k,v in x.items():
...     for i in v:
...             x2[i].append(k)
... 
>>> x2
defaultdict(<type 'list'>, {1: ['a'], 2: ['a'], 3: ['a','b'], 4: ['a','b'], 5: ['b'], 6: ['b']})

Solution

  • I believe the best way is to simply loop as you did:

    target = defaultdict(list)
    for key, values in original.items():
        for value in values:
            target[value].append(key)
    

    Alternatively you could avoid the inner for:

    for key, values in original.items():
        target.update(zip(values, [key] * len(values)))
    

    Or using itertools.repeat:

    import itertools as it
    
    for key, values in original.items():
        target.update(zip(values, it.repeat(key)))
    

    However these last solutions only work for the simple case where values in different lists are distinct.


    Remember that pythonic doesn't have any definite meaning. I'd consider python a solution that is:

    1. Readable
    2. Correctly use the language features
    3. Correctly use the built-ins/standard library
    4. Efficient

    And the points are in order of importance. Efficience is last because it is most often implied by point 2 and 3.