Reputation: 26315
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 :)
Upvotes: 16
Views: 14056
Reputation: 4418
Slightly different take on a solution:
import collections
phonemes = ["W", "IY", "O", "W", "O"]
graphemes = ["w", "ee", "o", "w", "oh"]
# count all the (phoneme, grapheme) pairs
counter = collections.Counter(zip(phonemes, graphemes))
# convert to desired data structure
d = collections.defaultdict(dict)
for (phoneme, grapheme), count in counter.items():
d[phoneme][grapheme] = count
print(d)
prints:
defaultdict(<class 'dict'>, {'W': {'w': 2}, 'O': {'oh': 1, 'o': 1}, 'IY': {'ee': 1}})
Upvotes: 2
Reputation: 73450
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.
Upvotes: 4
Reputation: 2397
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]}}
Upvotes: 3
Reputation: 23743
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
Upvotes: 6