I have a defaultdict that looks like this:
my_dict = defaultdict(dict)
which will print out:
defaultdict(<class 'dict'>, {})
I also have two lists, which look like this:
list1 = ["W", "IY", "W"]
list2 = ["w", "ee", "w"]
I would like to create a default dict which looks like this:
defaultdict(<class 'dict'>, {'W': {'w': 2}, 'IY': {'ee': 1}}
which has list1 within a dictionary as keys, with the keys as the next list with a separate dictionary, counting the instances of list2 as values.
So far I have this:
from collections import defaultdict
d = defaultdict(dict)
list1 = ["W", "IY", "W"]
list2 = ["w", "ee", "w"]
for char in list1:
d[char] += 1
I know that this is not correct, as the defaultdict(dict) cannot be treated this way. Is there a way a I could do this? Any help would be greatly appreciated :)
The main difference between defaultdict and dict is that when you try to access or modify a key that's not present in the dictionary, a default value is automatically given to that key . In order to provide this functionality, the Python defaultdict type does two things: It overrides .
defaultdict is not necessarily slower than a regular dict . The timings there are flawed, as the timings include creating the object. Other than that, there are different types of performance, maintenance ease being one.
You can add key to dictionary in python using mydict["newkey"] = "newValue" method. Dictionaries are changeable, ordered, and don't allow duplicate keys. However, different keys can have the same value.
Defaultdict is a sub-class of the dictionary class that returns a dictionary-like object. The functionality of both dictionaries and defaultdict are almost same except for the fact that defaultdict never raises a KeyError. It provides a default value for the key that does not exists.
Here is a solution using collections.Counter
.
import collections
d = collections.defaultdict(collections.Counter)
list1 = ["O", "TH", "O", "O"]
list2 = ["o", "th", "o", "o1"]
for key, value in zip(list1, list2):
d[key].update([value])
>>> d
defaultdict(<class 'collections.Counter'>, {'TH': Counter({'th': 1}), 'O': Counter({'o': 2, 'o1': 1})})
>>>
While this doesn't strictly follow your requirements, collections.Counter
inherits from dict
so it has all of dict
's attributes
You can also use a nested defaultdict and zip
like so:
d = defaultdict(lambda: defaultdict(int))
for k, v in zip(list1, list2):
d[k][v] += 1
# d['TH']['th']: 1
# d['O']['o']: 2
or, if you want to keep your data structure:
d = defaultdict(dict)
for k, v in zip(list1, list2):
d[k][v] = d[k].get(v, 0) + 1
# use dict.get(key, default=None) and specify an appropriate default value (0)
Using dict.get(key, default=None)
allows you to access key-values of a common dict
much like those a defaultdict, however, updating is a little more clunky.
EDITED based on the comment on my original answer.
You'll need a mapping of all possible phonemes to all possible spellings (graphemes).
phonemes = {TH : [th], O : [o], OH : [oh, oo]}
for char in set(list1):
if char not in d:
d[char] = {char.lower() : {phone : list2.count(phone) for phone in phonemes[char]}}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With