GBR24 GBR24 - 4 years ago 147
Python Question

Sub-dictionary erroneously repeated throughout dictionary?

I'm trying to store in a dictionary the number of times a given letter occurs after another given letter. For example,

dictionary['a']['d']
would give me the number of times
'd'
follows
'a'
in
short_list
.

alphabet = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
short_list = ['ford','hello','orange','apple']

# dictionary to keep track of how often a given letter occurs
tally = {}
for a in alphabet:
tally[a] = 0

# dictionary to keep track of how often a given letter occurs after a given letter
# e.g. how many times does 'd' follow 'a' -- master_dict['a']['d']
master_dict = {}
for a in alphabet:
master_dict[a] = tally

def precedingLetter(letter,word):
if word.index(letter) == 0:
return
else:
return word[word.index(letter)-1]

for a in alphabet:
for word in short_list:
for b in alphabet:
if precedingLetter(b,word) == a:
master_dict[a][b] += 1


However, the entries for all of the letters (the keys) in
master_dict
are all the same. I can't think of another way to properly tally each letter's occurrence after another letter. Can anyone offer some insight here?

Answer Source

If the sub-dicts are all supposed to be updated independently after creation, you need to shallow copy them. Easiest/fastest way is with .copy():

for a in alphabet:
    master_dict[a] = tally.copy()

The other approach is to initialize the dict lazily. The easiest way to do that is with defaultdict:

from collections import defaultdict

masterdict = defaultdict(lambda: defaultdict(int))

# or

from collections import Counter, defaultdict

masterdict = defaultdict(Counter)

No need to pre-create empty tallies or populate masterdict at all, and this avoids creating dicts when the letter never occurs. If you access masterdict[a] for an a that doesn't yet exist, it creates a defaultdict(int) value for it automatically. When masterdict[a][b] is accessed and doesn't exist, the count is initialized to 0 automatically.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download