web-dev-qa-db-fra.com

ajouter plusieurs valeurs pour une clé dans un dictionnaire

Je suis nouveau sur python et j'ai une liste d'années et de valeurs pour chaque année. Ce que je veux faire, c'est vérifier si l'année existe déjà dans un dictionnaire et, le cas échéant, ajouter la valeur à cette liste de valeurs pour la clé spécifique.

Ainsi, par exemple, j'ai une liste d'années et une valeur pour chaque année:

2010  
2  
2009  
4  
1989  
8  
2009  
7  

Ce que je veux faire, c'est remplir un dictionnaire avec les années comme clés et les nombres à un chiffre comme valeurs. Cependant, si 2009 est répertorié deux fois, je souhaite ajouter cette seconde valeur à la liste de valeurs de ce dictionnaire. Je souhaite donc:

2010: 2  
2009: 4, 7  
1989: 8  

À l'heure actuelle, j'ai les éléments suivants:

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  
124
anon

Si je peux reformuler votre question, vous voulez un dictionnaire avec les années sous forme de clés et un tableau pour chaque année contenant une liste de valeurs associées à cette année, n'est-ce pas? Voici comment je le ferais:

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

Avec years_dict, vous devriez vous retrouver avec un dictionnaire qui ressemble à ceci:

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

En général, il est peu courant en matière de programmation de créer des "tableaux parallèles", dans lesquels les éléments sont implicitement associés les uns aux autres en ayant le même index plutôt qu'en étant les enfants propres d'un conteneur qui les englobe tous les deux.

182
Faisal

Vous feriez mieux d'utiliser collections.defaultdict (ajouté dans Python 2.5). Cela vous permet de spécifier le type d'objet par défaut d'une clé manquante (telle que list).

Ainsi, au lieu de créer une clé si elle n’existait pas en premier lieu, puis d’ajouter à la valeur de la clé, vous supprimez l’homme du milieu et vous ajoutez directement les clés non existantes pour obtenir le résultat souhaité.

Un exemple rapide utilisant vos données:

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

De cette façon, vous n'avez pas à vous soucier de savoir si vous avez vu un chiffre associé à une année ou non. Vous ajoutez simplement et oubliez, sachant qu’une clé manquante sera toujours une liste. Si une clé existe déjà, elle sera simplement ajoutée à.

95
jathanism

Vous pouvez utiliser setdefault.

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

Cela fonctionne parce que setdefault renvoie la liste et la définit dans le dictionnaire, et comme une liste est modifiable, ajouter à la version renvoyée par setdefault revient à l'ajouter à la version à l'intérieur du dictionnaire. Si cela a du sens.

40
Daniel Roseman
d = {} 

# import list of year,value pairs

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

La méthode Python - il est plus facile de recevoir le pardon que de demander la permission!

17
Hugh Bothwell

Voici une autre façon de faire en utilisant l'opérateur 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)
12
USER_1

C'est plus facile si vous insérez ces valeurs dans une liste de n-uplets. Pour ce faire, vous pouvez utiliser le découpage de liste et la fonction Zip.

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

Zip prend un nombre arbitraire de listes, dans ce cas les entrées paires et impaires de data_in, et les regroupe dans un Tuple.

Nous pouvons maintenant utiliser la méthode setdefault.

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

setdefault prend une clé et une valeur par défaut et renvoie la valeur associée ou, en l'absence de valeur actuelle, la valeur par défaut. Dans ce cas, nous obtiendrons une liste vide ou remplie, à laquelle nous ajouterons ensuite la valeur actuelle.

4
erik

Si vous voulez un (presque) one-liner:

 à partir de collections importer deque 
 
 d = {} 
 deque ((d.setdefault (year, []). append (valeur) pour year, value in source_of_data), maxlen = 0) 

En utilisant dict.setdefault, vous pouvez intégrer l'idée de "vérifier si la clé existe déjà et créer une nouvelle liste sinon" en un seul appel. Cela vous permet d'écrire une expression de générateur consommée par deque aussi efficacement que possible car la longueur de la file d'attente est définie sur zéro. La deque sera immédiatement rejetée et le résultat sera dans d.

C'est quelque chose que je viens de faire pour m'amuser. Je ne recommande pas de l'utiliser. Il y a un temps et un endroit pour consommer des itérables arbitraires à travers une deque, et ce n'est certainement pas ça.

2
Mad Physicist