[python] append multiple values for one key in a dictionary

I am new to python and I have a list of years and values for each year. What I want to do is check if the year already exists in a dictionary and if it does, append the value to that list of values for the specific key.

So for instance, I have a list of years and have one value for each year:

2010  
2  
2009  
4  
1989  
8  
2009  
7  

What I want to do is populate a dictionary with the years as keys and those single digit numbers as values. However, if I have 2009 listed twice, I want to append that second value to my list of values in that dictionary, so I want:

2010: 2  
2009: 4, 7  
1989: 8  

Right now I have the following:

d = dict()  
years = []  

(get 2 column list of years and values)

for line in list:    
    year = line[0]   
    value = line[1]  

for line in list:  
    if year in d.keys():  
        d[value].append(value)  
    else:  
        d[value] = value  
        d[year] = year  

This question is related to python dictionary key-value

The answer is


You would be best off using collections.defaultdict (added in Python 2.5). This allows you to specify the default object type of a missing key (such as a list).

So instead of creating a key if it doesn't exist first and then appending to the value of the key, you cut out the middle-man and just directly append to non-existing keys to get the desired result.

A quick example using your data:

>>> from collections import defaultdict
>>> data = [(2010, 2), (2009, 4), (1989, 8), (2009, 7)]
>>> d = defaultdict(list)
>>> d
defaultdict(<type 'list'>, {})
>>> for year, month in data:
...     d[year].append(month)
... 
>>> d
defaultdict(<type 'list'>, {2009: [4, 7], 2010: [2], 1989: [8]})

This way you don't have to worry about whether you've seen a digit associated with a year or not. You just append and forget, knowing that a missing key will always be a list. If a key already exists, then it will just be appended to.


Here is an alternative way of doing this using the not in operator:

# define an empty dict
years_dict = dict()

for line in list:
    # here define what key is, for example,
    key = line[0]
    # check if key is already present in dict
    if key not in years_dict:
        years_dict[key] = []
    # append some value 
    years_dict[key].append(some.value)

d = {} 

# import list of year,value pairs

for year,value in mylist:
    try:
        d[year].append(value)
    except KeyError:
        d[year] = [value]

The Python way - it is easier to receive forgiveness than ask permission!


It's easier if you get these values into a list of tuples. To do this, you can use list slicing and the zip function.

data_in = [2010,2,2009,4,1989,8,2009,7]
data_pairs = zip(data_in[::2],data_in[1::2])

Zip takes an arbitrary number of lists, in this case the even and odd entries of data_in, and puts them together into a tuple.

Now we can use the setdefault method.

data_dict = {}
for x in data_pairs:
    data_dict.setdefault(x[0],[]).append(x[1])

setdefault takes a key and a default value, and returns either associated value, or if there is no current value, the default value. In this case, we will either get an empty or populated list, which we then append the current value to.


If you want a (almost) one-liner:

from collections import deque

d = {}
deque((d.setdefault(year, []).append(value) for year, value in source_of_data), maxlen=0)

Using dict.setdefault, you can encapsulate the idea of "check if the key already exists and make a new list if not" into a single call. This allows you to write a generator expression which is consumed by deque as efficiently as possible since the queue length is set to zero. The deque will be discarded immediately and the result will be in d.

This is something I just did for fun. I don't recommend using it. There is a time and a place to consume arbitrary iterables through a deque, and this is definitely not it.


You can use setdefault.

for line in list:  
    d.setdefault(year, []).append(value)

This works because setdefault returns the list as well as setting it on the dictionary, and because a list is mutable, appending to the version returned by setdefault is the same as appending it to the version inside the dictionary itself. If that makes any sense.


Examples related to python

programming a servo thru a barometer Is there a way to view two blocks of code from the same file simultaneously in Sublime Text? python variable NameError Why my regexp for hyphenated words doesn't work? Comparing a variable with a string python not working when redirecting from bash script is it possible to add colors to python output? Get Public URL for File - Google Cloud Storage - App Engine (Python) Real time face detection OpenCV, Python xlrd.biffh.XLRDError: Excel xlsx file; not supported Could not load dynamic library 'cudart64_101.dll' on tensorflow CPU-only installation

Examples related to dictionary

JS map return object python JSON object must be str, bytes or bytearray, not 'dict Python update a key in dict if it doesn't exist How to update the value of a key in a dictionary in Python? How to map an array of objects in React C# Dictionary get item by index Are dictionaries ordered in Python 3.6+? Split / Explode a column of dictionaries into separate columns with pandas Writing a dictionary to a text file? enumerate() for dictionary in python

Examples related to key-value

Iterate through dictionary values? How can I get key's value from dictionary in Swift? How to add a new object (key-value pair) to an array in javascript? How to search if dictionary value contains certain string with Python Python: How to check if keys exists and retrieve value from Dictionary in descending priority How do you create a dictionary in Java? how to prevent adding duplicate keys to a javascript array How to update value of a key in dictionary in c#? How to create dictionary and add key–value pairs dynamically? How to count frequency of characters in a string?