Search code examples
pythondictionarykeyerror

keyError: 'ba' when using setDefault method


So I'm basically trying to put a dictionary in a dictionary using the setdefault method.

text = 'banana'
k = 2

st = {}
circ_text = text + text[:k]
for i in range(len(circ_text) - k):
    kgram = circ_text[i:i + k]
    next_char = circ_text[i + k]
    st[kgram].setdefault(next_char, 0)
    st[kgram][next_char] += 1
print(st)

I'm trying to get something like this

st = {ba : {a : 1}
      an : {a : 2}
      .......
     }

For some reason I'm getting a keyError: 'ba'. So I'm I supposed to put 'ba' in the st dict before doing this? or is there way of adding the 'ba' key in this way


Solution

  • You need to support dynamic generation of dict entries at both levels. For this particular case, it's probably easiest to use a defaultdict for at least one of the levels (and since you're counting things, a Counter for the inner dict).

    from collections import defaultdict, Counter
    
    text = 'banana'
    k = 2
    
    st = defaultdict(Counter)
    circ_text = text + text[:k]
    for i in range(len(circ_text) - k):
        kgram = circ_text[i:i + k]
        next_char = circ_text[i + k]
        st[kgram][next_char] += 1
    print(st)
    

    That simplifies your code (no explicit handling of missing keys), though it does mean your output will not just use {} wrapping. If you want it to look like nested dicts at the end (and/or need to stop auto-vivifying keys as defaultdict and Counter do), you'd add:

    st = {k: dict(v) for k, v in st.items()}
    

    before the print and that would convert back to plain dict of dicts.