добавить несколько значений для одного ключа в словаре

Я новичок в python, и у меня есть список лет и значений за каждый год. То, что я хочу сделать, это проверить, существует ли уже год в словаре, и если это так, добавьте значение в этот список значений для конкретного ключа.

Так, например, у меня есть список лет и у меня есть одно значение за каждый год:

2010  
2  
2009  
4  
1989  
8  
2009  
7  

То, что я хочу сделать, это заполнить словарь с годами как ключами и этими цифрами в качестве значений. Однако, если в 2009 году я перечислял дважды, я хочу добавить это второе значение в свой список значений в этом словаре, поэтому хочу:

2010: 2  
2009: 4, 7  
1989: 8  

Сейчас у меня есть следующее:

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  

Ответ 1

Если я могу перефразировать ваш вопрос, то вам нужен словарь с годами в виде ключей и массив для каждого года, содержащий список значений, связанных с этим годом, не так ли? Вот как я это сделаю:

years_dict = dict()

for line in list:
    if line[0] in years_dict:
        # append the new number to the existing array at this slot
        years_dict[line[0]].append(line[1])
    else:
        # create a new array in this slot
        years_dict[line[0]] = [line[1]]

То, что вам должно получиться в years_dict, - это словарь, который выглядит следующим образом:

{
    "2010": [2],
    "2009": [4,7],
    "1989": [8]
}

В целом, это плохая практика программирования для создания "параллельных массивов", где элементы неявно связаны друг с другом с помощью одного и того же индекса, а не являются надлежащими дочерними элементами контейнера, который охватывает их обоих.

Ответ 2

Лучше всего использовать collections.defaultdict (добавлен в Python 2.5). Это позволяет указать тип объекта по умолчанию отсутствующего ключа (например, list).

Поэтому вместо того, чтобы создавать ключ, если он не существует первым, а затем добавляется к значению ключа, вы вырезаете среднего человека и просто добавляете к несуществующим клавишам, чтобы получить желаемый результат.

Быстрый пример использования ваших данных:

>>> 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]})

Таким образом, вам не нужно беспокоиться о том, видели ли вы цифру, связанную с годом или нет. Вы просто добавляете и забываете, зная, что отсутствующий ключ всегда будет списком. Если ключ уже существует, он будет просто добавлен.

Ответ 3

Вы можете использовать setdefault.

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

Это работает, потому что setdefault возвращает список, а также устанавливает его в словаре, а поскольку список изменен, добавление к версии, возвращаемой setdefault, аналогично добавлению к версии внутри самого словаря. Если это имеет смысл.

Ответ 4

d = {} 

# import list of year,value pairs

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

Путь Python - легче получить прощение, чем запросить разрешение!

Ответ 5

Вот альтернативный способ сделать это с помощью оператора not in:

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

Ответ 6

Это проще, если вы получите эти значения в список кортежей. Для этого вы можете использовать нарезку списка и функцию zip.

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

Zip принимает произвольное количество списков, в этом случае четные и нечетные записи data_in, и складывает их в кортеж.

Теперь мы можем использовать метод setdefault.

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

setdefault берет ключ и значение по умолчанию и возвращает либо связанное значение, либо если нет текущего значения, значение по умолчанию. В этом случае мы либо получим пустой или заполненный список, который затем добавим текущее значение.

Ответ 7

Если вы хотите (почти) однострочник:

from collections import deque

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

Используя dict.setdefault, вы можете инкапсулировать идею "проверить, существует ли ключ, и создать новый список, если нет" в одном вызове. Это позволяет вам написать выражение генератора, которое будет использоваться deque настолько эффективно, насколько это возможно, так как длина очереди установлена на ноль. Deque будет немедленно отброшен, и результат будет в d.

Это то, что я просто сделал для развлечения. Я не рекомендую использовать это. Есть время и место для использования произвольных итераций через deque, и это определенно не так.