web-dev-qa-db-fra.com

Attribuer une valeur à une cellule individuelle dans un tableau python à deux dimensions

Disons que j'ai le tableau vide à deux dimensions suivant en Python:

q = [[None]*5]*4

Je veux attribuer une valeur de 5 à la première ligne de la première colonne de q. Instinctivement, je fais ce qui suit:

q[0][0] = 5

Cependant, cela produit:

 [[5, None, None, None, None], 
  [5, None, None, None, None], 
  [5, None, None, None, None], 
  [5, None, None, None, None]]

Le premier élément de every array est en cours d'initialisation à 5, où je pensais que seul le premier élément du premier tableau obtiendrait la mise à jour. J'ai deux questions:

  1. Pourquoi Python initialise-t-il la première valeur de chaque tableau et pas seulement la première?
  2. Y a-t-il une meilleure façon d'accomplir ce que j'essaie de faire?
20
Ben McCormack

Cela ne fait pas ce que tu espérais.

q = [[None]*5]*4

Il réutilise les objets list plusieurs fois. Comme vous pouvez le constater lorsque vous avez modifié une cellule qui se trouvait dans un objet de liste réutilisé.

Une liste unique avec la valeur [None] est utilisée cinq fois.

Une liste unique avec une valeur de [[None]*5] est utilisée quatre fois.

q = [ [ None for i in range(5) ] for j in range(4) ]

Peut-être plus ce que vous cherchez.

Cela évite explicitement de réutiliser un objet de la liste.

80% du temps, un dictionnaire est ce que vous vouliez vraiment.

q = {}
q[0,0]= 5

Travaillera également. Vous ne commencez pas par une grille prédéfinie de valeurs None. Mais c'est rare d'en avoir besoin en premier lieu.

Vous pouvez le faire dans Python 2.7 et supérieur.

q = { (i,j):0 for i in range(5) for j in range(4) }

Cela construira une grille indexée par 2-tuples.

{(0, 1): 0, (1, 2): 0, (3, 2): 0, (0, 0): 0, (3, 3): 0, (3, 0): 0, (3, 1): 0, (2, 1): 0, (0, 2): 0, (2, 0): 0, (1, 3): 0, (2, 3): 0, (4, 3): 0, (2, 2): 0, (1, 0): 0, (4, 2): 0, (0, 3): 0, (4, 1): 0, (1, 1): 0, (4, 0): 0}
42
S.Lott

La raison en est que vous avez la liste, juste dupliquée quatre fois! Python ne régénère pas cette liste à chaque fois que vous utilisez *4. Il utilise le même objet de liste.

Pour résoudre ce problème, forcez python à régénérer cette liste pour vous chaque fois:

[ [None] * 5 for i1 in range(4) ]

Dans ce cas, j'utilise une compréhension de liste.

6
Donald Miner
q = [[None]*5]*4
print(q)
q[1][1]=4
print(q)
q = [ [ None for i in range(5) ] for j in range(4) ]
q[1][1]=4
print(q)

résultat :

[[None, None, None, None, None], [None, None, None, None, None], [None, None, None, None, None], [None, None, None, None, None]]
[[None, 4, None, None, None], [None, 4, None, None, None], [None, 4, None, None, None], [None, 4, None, None, None]]
[[None, None, None, None, None], [None, 4, None, None, None], [None, None, None, None, None], [None, None, None, None, None]]
4
Jin Thakur

La réponse est simple Ne jamais utiliser 

q = [[None]*5]*4

comme lorsque vous faites une affectation 

q[0][1]=5 il affecte plusieurs fois la valeur à plusieurs lignes en une colonne try print (q)

plutôt utiliser 

q = { (i,j):0 for i in range(5) for j in range(4) }

alors q[0][1]=5 assignera une seule fois try 

print(q)
1
Jin Thakur

Si vous souhaitez utiliser une liste et non un dictionnaire comme le proposent les autres, vous pouvez utiliser ceci:

q[0] = [5,None,None,None,None]
0
manosbar

Pourquoi Python initialise-t-il la première valeur de chaque tableau et pas seulement la première?

Parce qu'ils sont le même tableau, référencé plusieurs fois.

Y a-t-il une meilleure façon d'accomplir ce que j'essaie de faire?

Créez la structure de sorte que le tableau externe fasse référence à des tableaux internes distincts au lieu de les réutiliser. Les autres réponses fournissent des moyens de le faire.

0
Karl Knechtel

La réponse à la question n ° 2: Utiliser numpy est une option. Voir le code suivant.

import numpy as np

# creating 2D array with nans
num_of_rows = 5
num_of_cols = 3
a = np.full((num_of_rows, num_of_cols), np.nan) 
#for zero vals: a = np.zeros((num_of_rows, num_of_cols))

# placing number 5 in row 3, col 1
value = [5]
position_row = 3
position_col = 1
# the put command below flattens the 2D array
position = [int(num_of_cols * position_row + position_col)] 
np.put(a, position, value)

résultat:

[[ nan  nan  nan]
 [ nan  nan  nan]
 [ nan  nan  nan]
 [ nan   5.  nan]
 [ nan  nan  nan]]
0
SDJ