Search code examples
pythonlistdictionarydefaultdict

How to update the list elements in a defaultdict(list) dictionary?


I am using Python's collections library to make a dictionary where the keys are integers and the values are lists. I am using the defaultdict(list) command. I am trying, but unsuccessfully to edit the elements in these lists which are values.

I thought list comprehension should work for this but I keep getting syntax errors. I attach what I have tried below:

import collections 

test = collections.defaultdict(list) 
test[4].append(1)
test[4].append(5)
test[4].append(6)
#This would yield {4: [1,5,6]}

run_lengths = [1,3,4,6] #dummy data

for i in run_lengths:
    #I would like to add 3 to each element of these lists which are values.
    test[i][j for j in test[i]] += i

Solution

  • Assuming you want to modify the list in place, you need to overwrite each element as integers are immutable:

    test[4][:] = [e+3 for e in test[4]]
    

    Output:

    defaultdict(list, {4: [4, 8, 9]})
    

    If you don't care about generating a new object (i.e. you did not link a variable name to test[4] you can just use:

    test[4] = [e+3 for e in test[4]]
    

    what is the difference?

    The first case modifies the list in place. If other variables point to the list, the changes will be reflected:

    x = test[4]
    test[4][:] = [e+3 for e in test[4]]
    print(x, test)
    # [4, 8, 9] defaultdict(<class 'list'>, {4: [4, 8, 9]})
    

    In the other case, the list is replaced by a new, independent, one,. All potential bindings are lost:

    x = test[4]
    test[4] = [e+3 for e in test[4]]
    print(x, test)
    # [1, 5, 6] defaultdict(<class 'list'>, {4: [4, 8, 9]})
    

    in your loop

    Assuming run_lengths contains a list of keys to update:

    for i in run_lengths:
        test[i][:] = [e+3 for e in test[i]]