web-dev-qa-db-fra.com

Stockage et mise à jour des listes dans les dictionnaires Python: pourquoi cela se produit-il?

J'ai une liste de données qui ressemble à ceci:

// timestep,x_position,y_position
0,4,7
0,2,7
0,9,5
0,6,7
1,2,5
1,4,7
1,9,0
1,6,8

... et je veux que cela ressemble à ceci:

0, (4,7), (2,7), (9,5), (6,7)
1, (2,5), (4,7), (9,0), (6.8)

Mon plan était d'utiliser un dictionnaire, où la valeur de t est la clé du dictionnaire, et la valeur par rapport à la clé serait une liste. Je pourrais ensuite ajouter chacun (x, y) à la liste. Quelque chose comme:

# where t = 0, c = (4,7), d = {}

# code 1
d[t].append(c)

Maintenant, cela entraîne l'échec d'IDLE. Cependant, si je le fais:

# code 2
d[t] = []
d[t].append(c)

... cela marche.

La question est donc: pourquoi le code 2 fonctionne-t-il, mais pas le code 1?

PS Toute amélioration de ce que je prévois de faire serait d'un grand intérêt !! Je pense que je vais devoir vérifier le dictionnaire sur chaque boucle via l'entrée pour voir si la clé du dictionnaire existe déjà, je suppose en utilisant quelque chose comme max (d.keys ()): s'il est là, ajouter des données, sinon créer la liste vide comme valeur de dictionnaire, puis ajoutez des données sur la boucle suivante.

27
user41121

Regardons

d[t].append(c)

Quelle est la valeur de d[t]? Essayez-le.

d = {}
t = 0
d[t]

Qu'est ce que tu obtiens? Oh. Il n'y a rien dans d qui a une clé de t.

Maintenant, essayez ceci.

d[t] = []
d[t]

Ahh. Maintenant, il y a quelque chose dans d avec une clé de t.

Vous pouvez faire plusieurs choses.

  1. Utilisez l'exemple 2.
  2. Utilisez setdefault. d.setdefault(t,[]).append(c).
  3. Utilisez collections.defaultdict . Vous utiliseriez une defaultdict(list) au lieu d'un simple dictionnaire, {}.

Édition 1. Optimisation

Étant donné les lignes d'entrée d'un fichier sous la forme ci-dessus: ts, x, y, le processus de regroupement est inutile. Il n'y a aucune raison de passer d'une simple liste de (ts, x, y) à une liste plus complexe de (ts, (x, y), (x, y), (x, y), ...). La liste d'origine peut être traitée exactement telle qu'elle est arrivée.

d= collections.defaultdict(list)
for ts, x, y in someFileOrListOrQueryOrWhatever:
    d[ts].append( (x,y) )

Modifier 2. Répondre à la question

"lors de l'initialisation d'un dictionnaire, vous devez indiquer au dictionnaire à quoi ressemblera la structure de données de valeur-clé?"

Je ne sais pas ce que signifie la question. Depuis, tous les dictionnaires sont structures de valeurs-clés, la question n'est pas très claire. Je vais donc passer en revue les trois alternatives, qui peuvent répondre à la question.

Exemple 2 .

Initialisation

d= {}

Utilisation

if t not in d:
    d[t] = list()
d[t].append( c )

Chaque valeur de dictionnaire doit être initialisée selon une structure utile. Dans ce cas, nous vérifions si la clé est présente; lorsque la clé est manquante, nous créons la clé et assignons une liste vide.

Setdefault

Initialisation

d= {}

Utilisation

d.setdefault(t,list()).append( c )

Dans ce cas, nous exploitons la méthode setdefault pour récupérer une valeur associée à une clé ou créer une nouvelle valeur associée à une clé manquante.

dict par défaut

Initialisation

import collections
d = collections.defaultdict(list)

Utilisation

d[t].append( c )

defaultdict utilise une fonction d'initialisation pour les clés manquantes. Dans ce cas, nous fournissons la fonction list afin qu'une nouvelle liste vide soit créée pour une clé manquante.

72
S.Lott

Je pense que vous voulez utiliser setdefault. C'est un peu bizarre à utiliser mais fait exactement ce dont vous avez besoin.

d.setdefault(t, []).append(c)

Le .setdefault la méthode retournera l'élément (dans notre cas, une liste) qui est lié à la clé du dict t si cette clé existe. Si ce n'est pas le cas, il liera une liste vide à la clé t et la renverra. Donc, de toute façon, une liste sera là que le .append peut ensuite ajouter le Tuple c à.

12
Tim Pietzcker
dict=[]  //it's not a dict, it's a list, the dictionary is dict={}
elem=[1,2,3]
dict.append(elem)

vous pouvez accéder à l'élément unique de cette façon:

print dict[0] // 0 is the index

la sortie sera:

[1, 2, 3]
1
Giancarlo

Dans le cas où vos données ne sont pas déjà triées selon les critères souhaités, voici le code qui pourrait aider à regrouper les données:

#!/usr/bin/env python
"""
$ cat data_shuffled.txt
0,2,7
1,4,7
0,4,7
1,9,0
1,2,5
0,6,7
1,6,8
0,9,5
"""
from itertools   import groupby
from operator    import itemgetter

# load the data and make sure it is sorted by the first column
sortby_key = itemgetter(0)
data = sorted((map(int, line.split(',')) for line in open('data_shuffled.txt')),
              key=sortby_key)

# group by the first column
grouped_data = []
for key, group in groupby(data, key=sortby_key):
    assert key == len(grouped_data) # assume the first column is 0,1, ...
    grouped_data.append([trio[1:] for trio in group])

# print the data
for i, pairs in enumerate(grouped_data):
    print i, pairs

Production:

0 [[2, 7], [4, 7], [6, 7], [9, 5]]
1 [[4, 7], [9, 0], [2, 5], [6, 8]]
1
jfs