Estoy empezando a usar Python e intento usar una lista bidimensional, que inicialmente llené con la misma variable en cada lugar. Se me ocurrió esto:
def initialize_twodlist(foo):
twod_list = []
new = []
for i in range (0, 10):
for j in range (0, 10):
new.append(foo)
twod_list.append(new)
new = []
Da el resultado deseado, pero se siente como una solución alternativa. ¿Hay una manera más fácil / más corta / más elegante de hacer esto?
python
multidimensional-array
thepandaatemyface
fuente
fuente
Respuestas:
Un patrón que a menudo surgió en Python fue
que ayudó a motivar la introducción de las comprensiones de listas, que convierten ese fragmento en
que es más corto y a veces más claro. Por lo general, tiene el hábito de reconocerlos y, a menudo, reemplazar los bucles con comprensiones.
Su código sigue este patrón dos veces
fuente
[foo] * 10
es una lista con exactamente las mismasfoo
10 veces, que puede o no ser importante.[foo] * 10
: Esto significa que este no funcionaría si usted está llenando una matriz con números aleatorios (evalúa[random.randint(1,2)] * 10
a[1] * 10
, o[2] * 10
lo que significa que se obtiene una matriz de todos los 1s o 2s, en lugar de una disposición al azar.Puedes usar una lista de comprensión :
fuente
i
para filas yj
columnas, creo que debería ser mejor intercambiari
yj
en su sintaxis para una mejor comprensión y cambiar el rango a 2 números diferentes.¡No lo uses
[[v]*n]*n
, es una trampa!pero
Funciona genial.
fuente
*
está copiando eladdress
del objeto (lista).[[0] * col for _ in range(row)]
.De esta manera es más rápido que las comprensiones de la lista anidada
Aquí hay algunos tiempos de python3, para listas pequeñas y grandes
Explicación:
[[foo]*10]*10
crea una lista del mismo objeto repetido 10 veces. ¡No puedes usar esto, porque modificar un elemento modificará el mismo elemento en cada fila!x[:]
es equivalentelist(X)
pero es un poco más eficiente ya que evita la búsqueda de nombres. De cualquier manera, crea una copia superficial de cada fila, por lo que ahora todos los elementos son independientes.Sin
foo
embargo, todos los elementos son el mismo objeto, por lo que sifoo
es mutable , no puede usar este esquema., Tendría que usaro suponiendo una clase (o función)
Foo
que devuelvefoo
sfuente
copy.deepcopy
. Necesita un plan específico para sus datos si tiene un objeto mutable arbitrario.x
yy
. ¿No debería ser[[copy.deepcopy(foo) for y in range(10)] for x in range(10)]
[foo]*10
no crea 10 objetos diferentes, pero es fácil pasar por alto la diferencia en el caso de que foo sea inmutable, como unint
ostr
.Para inicializar una matriz bidimensional en Python:
fuente
a = [[0 for x in range(columns)] for y in range(rows)]
.fuente
[[0] * col] * row
no hace lo que quiere es porque cuando inicializa una lista 2d de esa manera, Python no creará copias distintas de cada fila. En su lugar, iniciará la lista externa con punteros a la misma copia de[0]*col
. Cualquier edición que realice en una de las filas se reflejará en las filas restantes, ya que todas apuntan a los mismos datos en la memoria.Por lo general, cuando desea matrices multidimensionales, no desea una lista de listas, sino más bien una matriz numpy o posiblemente un dict.
Por ejemplo, con numpy harías algo como
fuente
numpy
es genial, creo que puede ser un poco exagerado para un principiante.numpy
. +1Puedes hacer exactamente esto:
Por ejemplo:
Pero esto tiene un efecto secundario no deseado:
fuente
para n es el número de filas, y m es el número de columna, y foo es el valor.
fuente
Si se trata de una matriz escasamente poblada, es mejor que utilice un diccionario con una tupla:
fuente
para cada elemento se
[0]*10
creará un nuevo .fuente
Enfoque incorrecto: [[Ninguno * m] * n]
Con este enfoque, Python no permite crear un espacio de direcciones diferente para las columnas externas y dará lugar a un mal comportamiento diferente al esperado.
Enfoque correcto pero con excepción:
Es un buen enfoque, pero hay una excepción si establece el valor predeterminado en
None
Establezca su valor predeterminado correctamente utilizando este enfoque.
Absolutamente correcto:
Sigue la respuesta del micrófono de doble bucle .
fuente
fuente
Para inicializar un uso de matriz bidimensional:
arr = [[]*m for i in range(n)]
Realmente,
arr = [[]*m]*n
creará una matriz 2D en la que todas las n matrices apuntarán a la misma matriz, por lo que cualquier cambio en el valor de cualquier elemento se reflejará en todas las n listasPara obtener más información, visite: https://www.geeksforgeeks.org/python-using-2d-arrays-lists-the-right-way/
fuente
usa el pensamiento más simple para crear esto.
y agrega el tamaño:
o si queremos declarar el tamaño en primer lugar. solo usamos:
fuente
Como señalaron @Arnab y @Mike, una matriz no es una lista. Pocas diferencias son 1) las matrices son de tamaño fijo durante la inicialización 2) las matrices normalmente admiten operaciones menores que una lista.
Tal vez una exageración en la mayoría de los casos, pero aquí hay una implementación básica de matriz 2d que aprovecha la implementación de matriz de hardware utilizando python ctypes (bibliotecas c)
fuente
Lo importante que entendí es: al inicializar una matriz (en cualquier dimensión) Deberíamos dar un valor predeterminado a todas las posiciones de la matriz. Entonces solo se completa la inicialización. Después de eso, podemos cambiar o recibir nuevos valores en cualquier posición de la matriz. El siguiente código me funcionó perfectamente
fuente
Si usa numpy , puede crear fácilmente matrices 2d:
X
fuente
Lo anterior le dará una matriz 2D de 5x5
Está utilizando la comprensión de la lista anidada. Desglose de la siguiente manera:
[x] * col -> la expresión final que se evalúa
para x en -> x será el valor proporcionado por el iterador
[b para b en el rango (fila)]] -> Iterador.
[b para b en rango (fila)]] esto se evaluará a [0,1,2,3,4] ya que fila = 5,
así que ahora se simplifica a
Esto evaluará a [[0] * 5 para x en [0,1,2,3,4]] -> con x = 0 1ª iteración
[[1] * 5 para x en [0,1,2, 3,4]] -> con x = 1 2da iteración
[[2] * 5 para x en [0,1,2,3,4]] -> con x = 2 3ra iteración
[[3] * 5 para x en [0,1,2,3,4]] -> con x = 3 4ta iteración
[[4] * 5 para x en [0,1,2,3,4]] -> con x = 4 5ta iteración
fuente
Esto es lo mejor que he encontrado para enseñar a nuevos programadores y sin usar bibliotecas adicionales. Aunque me gustaría algo mejor.
fuente
Aquí hay una manera más fácil:
Para inicializar todas las celdas con cualquier valor 'x' use:
fuente
A menudo uso este enfoque para inicializar una matriz bidimensional
n=[[int(x) for x in input().split()] for i in range(int(input())]
fuente
El patrón general para agregar dimensiones podría extraerse de esta serie:
fuente
Puedes probar esto [[0] * 10] * 10. Esto devolverá la matriz 2D de 10 filas y 10 columnas con valor 0 para cada celda.
fuente
a = [[0]*10]*10
ya[0][0] = 1
verá que el primer elemento en cada fila ahora es igual a 1lst = [[0] * m para i en el rango (n)]
inicializar toda la matriz n = filas ym = columnas
fuente
Otra forma es usar un diccionario para contener una matriz bidimensional.
Esto solo puede contener cualquier valor 1D, 2D y para inicializar esto
0
o cualquier otro valor int, use colecciones .fuente
Código:
initial_val
debe ser inmutablefuente
fuente