Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding keys to defaultdict(dict)

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 :)

like image 550
RoadRunner Avatar asked Apr 29 '16 02:04

RoadRunner


People also ask

What is the difference between Defaultdict and dict?

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 .

Is Defaultdict slower than dict?

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.

How do you assign a key to a dictionary in python?

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.

How does Defaultdict work Defaultdict stores a copy of a dictionary?

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.


3 Answers

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

like image 118
wwii Avatar answered Oct 17 '22 18:10

wwii


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.

like image 4
user2390182 Avatar answered Oct 17 '22 20:10

user2390182


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]}}
like image 3
aberger Avatar answered Oct 17 '22 18:10

aberger