How to Convert Defaultdict to Dict

How to convert defaultdict to dict?

You can simply call dict:

>>> a
defaultdict(<type 'list'>, {'1': ['b', 'a'], '3': ['b'], '2': ['a']})
>>> dict(a)
{'1': ['b', 'a'], '3': ['b'], '2': ['a']}

but remember that a defaultdict is a dict:

>>> isinstance(a, dict)
True

just with slightly different behaviour, in that when you try access a key which is missing -- which would ordinarily raise a KeyError -- the default_factory is called instead:

>>> a.default_factory
<type 'list'>

That's what you see when you print a before the data side of the dictionary appears.

So another trick to get more dictlike behaviour back without actually making a new object is to reset default_factory:

>>> a.default_factory = None
>>> a[4].append(10)
Traceback (most recent call last):
File "<ipython-input-6-0721ca19bee1>", line 1, in <module>
a[4].append(10)
KeyError: 4

but most of the time this isn't worth the trouble.

How to convert defaultdict of defaultdicts [of defaultdicts] to dict of dicts [of dicts]?

You can recurse over the tree, replacing each defaultdict instance with a dict produced by a dict comprehension:

def default_to_regular(d):
if isinstance(d, defaultdict):
d = {k: default_to_regular(v) for k, v in d.items()}
return d

Demo:

>>> from collections import defaultdict
>>> factory = lambda: defaultdict(factory)
>>> defdict = factory()
>>> defdict['one']['two']['three']['four'] = 5
>>> defdict
defaultdict(<function <lambda> at 0x103098ed8>, {'one': defaultdict(<function <lambda> at 0x103098ed8>, {'two': defaultdict(<function <lambda> at 0x103098ed8>, {'three': defaultdict(<function <lambda> at 0x103098ed8>, {'four': 5})})})})
>>> default_to_regular(defdict)
{'one': {'two': {'three': {'four': 5}}}}

How can I convert defaultdict(Set) to defaultdict(list)?

You can use following:

>>> values = defaultdict(Set)
>>> values['a'].add(1)
>>> defaultdict(list, ((k, list(v)) for k, v in values.items()))
defaultdict(<type 'list'>, {'a': [1]})

defaultdict constructor takes default_factory as a first argument which can be followed by the same arguments as in normal dict. In this case the second argument is a generator expression that returns tuples consisting key and value.

Note that if you only need to store it as a JSON normal dict will do just fine:

 >>> {k: list(v) for k, v in values.items()}
{'a': [1]}

Exposing `defaultdict` as a regular `dict`

defaultdict docs say for default_factory:

If the default_factory attribute is None, this raises a KeyError
exception with the key as argument.

What if you just set your defaultdict's default_factory to None? E.g.,

>>> d = defaultdict(int)
>>> d['a'] += 1
>>> d
defaultdict(<type 'int'>, {'a': 1})
>>> d.default_factory = None
>>> d['b'] += 2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'b'
>>>

Not sure if this is the best approach, but seems to work.

Removing defaultdict from print statement

You can construct a regular dict from a defaultdict:

>>> d
defaultdict(<class 'int'>, {'a': 1, 'b': 2})
>>> dict(d)
{'a': 1, 'b': 2}

Note that if the dict is nested such that some of the values are themselves defaultdicts, converting the top level dict won't do anything to those nested values.

How to convert a dict string with value default dict to an actual dict

A quick and dirty way to parse it is to replace the <class 'int'> notation with the actual class name, and then eval the string:

from collections import defaultdict
import re
s = '''"{'key1': 0, 'key2': defaultdict(<class 'int'>, {'total': 9, 'semcor': 9})}"'''
eval(re.sub(r"<class '(\w+)'>", r'\1', s))

This returns:

{'key1': 0, 'key2': defaultdict(int, {'total': 9, 'semcor': 9})}


Related Topics



Leave a reply



Submit