2012-02-27 20 views
15

Digamos que tengo el siguiente matriz bidimensional vacío en Python:valor Asignar a una celda individual en una matriz de dos pitón dimensiones

q = [[None]*5]*4 

quiero asignar un valor de 5 a la primera fila de la primera columna de q. Instintivamente, hacer lo siguiente:

q[0][0] = 5 

Sin embargo, esto produce:

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

El primer elemento de cada array se inicializa a 5, donde pensé sólo el primer elemento de la primera array obtendría la actualización. Tengo dos preguntas:

  1. ¿Por qué Python inicializa el primer valor de cada matriz y no solo la primera?
  2. ¿Hay alguna manera mejor de lograr lo que estoy tratando de hacer?

Respuesta

31

Esto no hace lo que esperaba.

q = [[None]*5]*4 

Reutiliza list objetos varias veces. Como puede ver cuando hizo un cambio en una celda, que estaba en un objeto de lista reutilizado.

Una sola lista con un valor de [None] se utiliza cinco veces.

Una sola lista con un valor de [[None]*5] se usa cuatro veces.

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

Sería más lo que estás buscando.

Esto explícitamente evita reutilizar un objeto de lista.

80% de las veces, un diccionario es lo que realmente quería.

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

También funcionará. No empiezas con una grilla predefinida de valores None. Pero es raro que los necesite en primer lugar.

En Python 2.7 y versiones posteriores, puede hacerlo.

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

Eso construirá una cuadrícula indexada por 2 tuplas.

{(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} 
+0

+1 para diccionario como matriz. –

+1

Le daré +1 si comparte la investigación que condujo a ese valor del 80%. –

+2

Es el Principio de Pareto. http://en.wikipedia.org/wiki/Pareto_principle. 80% del tiempo, solo necesita el 20% de las estructuras de datos. –

5

La razón por la que tiene la lista, ¡solo se ha duplicado cuatro veces! Python no está regenerando esa lista cada vez que lo hace *4. Está usando el mismo objeto de lista.

Para evitar esto, es necesario para la fuerza de pitón a regenrate esa lista para que cada vez que:

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

En este caso, estoy usando una lista por comprensión.

0

¿Por qué Python inicializa el primer valor de cada matriz y no solo la primera?

Porque son el mismo conjunto, al que se hace referencia varias veces.

¿Hay una manera mejor de lograr lo que estoy tratando de hacer?

Crea la estructura de modo que la matriz externa se refiera a matrices internas separadas en lugar de reutilizar una. Las otras respuestas proporcionan formas de hacerlo.

1

La respuesta es simple Nunca use

q = [[None]*5]*4 

como cuando lo hace la asignación

q[0][1]=5 asigna valor de tiempo múltiple de varias filas a 1 columna impresión de prueba (q)

prefiere usar

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

then q[0][1]=5 asignará una sola vez tratar

print(q) 
2
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) 

resultado:

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

En caso de que quiera utilizar una lista y no un diccionario como los otros proponen puede utilizar esto:

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

La respuesta a la pregunta número 2: Usando numpy es una opción. Ver el siguiente código

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) 

resultado:

[[ nan nan nan] 
[ nan nan nan] 
[ nan nan nan] 
[ nan 5. nan] 
[ nan nan nan]] 
Cuestiones relacionadas