unir - ¿Cómo inicializar una matriz bidimensional en Python?
unir dos matrices en python (20)
Estoy empezando python y estoy tratando de usar una lista bidimensional, que inicialmente llena 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. ¿Hay una manera más fácil / más corta / más elegante de hacer esto?
Enfoque incorrecto: [[Ninguno * m] * n]
>>> m, n = map(int, raw_input().split())
5 5
>>> x[0][0] = 34
>>> x
[[34, None, None, None, None], [34, None, None, None, None], [34, None, None, None, None], [34, None, None, None, None], [34, None, None, None, None]]
>>> id(x[0][0])
140416461589776
>>> id(x[3][0])
140416461589776
Con este enfoque, Python no permite crear un espacio de direcciones diferente para las columnas externas y conducirá a un mal comportamiento diferente al que espera.
Enfoque correcto pero con excepción:
y = [[0 for i in range(m)] for j in range(n)]
>>> id(y[0][0]) == id(y[1][0])
False
Es un buen enfoque pero hay una excepción si establece el valor predeterminado en None
>>> r = [[None for i in range(5)] for j in range(5)]
>>> r
[[None, None, None, None, None], [None, None, None, None, None], [None, None, None, None, None], [None, None, None, None, None], [None, None, None, None, None]]
>>> id(r[0][0]) == id(r[2][0])
True
Así que establezca su valor predeterminado correctamente utilizando este enfoque.
Absolutamente correcto:
Sigue la respuesta de mike de doble bucle .
A menudo utilizo este enfoque para inicializar una matriz bidimensional.
n=[[int(x) for x in input().split()] for i in range(int(input())]
Aquí hay una manera más fácil:
import numpy as np
twoD = np.array([[]*m]*n)
Para inicializar todas las celdas con cualquier valor ''x'' use:
twoD = np.array([[x]*m]*n
Como @Arnab y @Mike señalaron, una matriz no es una lista. Pocas diferencias son 1) las matrices tienen un tamaño fijo durante la inicialización 2) las matrices normalmente admiten menos operaciones que una lista.
Tal vez sea una exageración en la mayoría de los casos, pero aquí hay una implementación básica de la matriz 2d que aprovecha la implementación de la matriz de hardware usando ctypes de Python (bibliotecas c)
import ctypes
class Array:
def __init__(self,size,foo): #foo is the initial value
self._size = size
ArrayType = ctypes.py_object * size
self._array = ArrayType()
for i in range(size):
self._array[i] = foo
def __getitem__(self,index):
return self._array[index]
def __setitem__(self,index,value):
self._array[index] = value
def __len__(self):
return self._size
class TwoDArray:
def __init__(self,columns,rows,foo):
self._2dArray = Array(rows,foo)
for i in range(rows):
self._2dArray[i] = Array(columns,foo)
def numRows(self):
return len(self._2dArray)
def numCols(self):
return len((self._2dArray)[0])
def __getitem__(self,indexTuple):
row = indexTuple[0]
col = indexTuple[1]
assert row >= 0 and row < self.numRows() /
and col >=0 and col < self.numCols(),/
"Array script out of range"
return ((self._2dArray)[row])[col]
if(__name__ == "__main__"):
twodArray = TwoDArray(4,5,5)#sample input
print(twodArray[2,3])
El patrón general para agregar dimensiones se podría dibujar de esta serie:
x = 0
mat1 = []
for i in range(3):
mat1.append(x)
x+=1
print(mat1)
x=0
mat2 = []
for i in range(3):
tmp = []
for j in range(4):
tmp.append(x)
x+=1
mat2.append(tmp)
print(mat2)
x=0
mat3 = []
for i in range(3):
tmp = []
for j in range(4):
tmp2 = []
for k in range(5):
tmp2.append(x)
x+=1
tmp.append(tmp2)
mat3.append(tmp)
print(mat3)
Este es el mejor que he encontrado para enseñar a nuevos programadores, y sin usar bibliotecas adicionales. Aunque me gustaría algo mejor.
def initialize_twodlist(value):
list=[]
for row in range(10):
list.append([value]*10)
return list
No uses [[v] * n] * n, ¡es una trampa!
>>> a = [[0]*3]*3
>>> a
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> a[0][0]=1
>>> a
[[1, 0, 0], [1, 0, 0], [1, 0, 0]]
pero t = [[0] * 3 para i en el rango (3)] es excelente
Para inicializar una matriz bidimensional en Python:
a = [[0 for x in range(columns)] for y in range(rows)]
Por lo general, cuando desea matrices multidimensionales no desea una lista de listas, sino una matriz numpy o posiblemente un dict.
Por ejemplo, con numpy harías algo como
import numpy
a = numpy.empty((10, 10))
a.fill(foo)
Puede utilizar una lista de comprensión :
x = [[foo for i in range(10)] for j in range(10)]
# x is now a 10x10 array of ''foo'' (which can depend on i and j if you want)
Puedes hacer esto:
[[element] * numcols] * numrows
Por ejemplo:
>>> [[''a''] *3] * 2
[[''a'', ''a'', ''a''], [''a'', ''a'', ''a'']]
Pero esto tiene un efecto secundario no deseado:
>>> b = [[''a'']*3]*3
>>> b
[[''a'', ''a'', ''a''], [''a'', ''a'', ''a''], [''a'', ''a'', ''a'']]
>>> b[1][1]
''a''
>>> b[1][1] = ''b''
>>> b
[[''a'', ''b'', ''a''], [''a'', ''b'', ''a''], [''a'', ''b'', ''a'']]
Si se trata de una matriz escasamente poblada, es mejor utilizar un diccionario con una tupla:
dict = {}
key = (a,b)
dict[key] = value
...
Un patrón que a menudo surgía en Python era
bar = []
for item in some_iterable:
bar.append(SOME EXPRESSION)
que ayudó a motivar la introducción de listas de comprensión, que convierten ese fragmento de código en
bar = [SOME EXPRESSION for item in some_iterable]
que es más corto ya veces más claro. Por lo general, se acostumbra a reconocerlos y, a menudo, a reemplazar los bucles por comprensiones.
Tu código sigue este patrón dos veces
twod_list = [] /
for i in range (0, 10): /
new = [] / can be replaced } this too
for j in range (0, 10): } with a list /
new.append(foo) / comprehension /
twod_list.append(new) /
Usa el pensamiento más simple para crear esto.
wtod_list = []
y añadir el tamaño:
wtod_list = [[0 for x in xrange(10))] for x in xrange(10)]
O si queremos declarar el tamaño en primer lugar. solo usamos
wtod_list = [[0 for x in xrange(10))] for x in xrange(10)]
De esta manera es más rápido que las listas de comprensión anidadas.
[x[:] for x in [[foo] * 10] * 10] # for immutable foo!
Aquí hay algunos tiempos de python3, para listas grandes y pequeñas
$python3 -m timeit ''[x[:] for x in [[1] * 10] * 10]''
1000000 loops, best of 3: 1.55 usec per loop
$ python3 -m timeit ''[[1 for i in range(10)] for j in range(10)]''
100000 loops, best of 3: 6.44 usec per loop
$ python3 -m timeit ''[x[:] for x in [[1] * 1000] * 1000]''
100 loops, best of 3: 5.5 msec per loop
$ python3 -m timeit ''[[1 for i in range(1000)] for j in range(1000)]''
10 loops, best of 3: 27 msec per loop
Explicación:
[[foo]*10]*10
crea una lista del mismo objeto repetida 10 veces. ¡No puedes simplemente usar esto, porque la modificación de un elemento modificará ese mismo elemento en cada fila!
x[:]
es equivalente a list(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 embargo, todos los elementos son el mismo objeto foo
, así que si foo
es mutable , no puedes usar este esquema. Tendrías que usar
import copy
[[copy.deepcopy(foo) for x in range(10)] for y in range(10)]
o asumiendo una clase (o función) Foo
que devuelve foo
s
[[Foo() for x in range(10)] for y in range(10)]
Matrix={}
for i in range(0,3):
for j in range(0,3):
Matrix[i,j] = raw_input("Enter the matrix:")
[[foo for x in xrange(10)] for y in xrange(10)]
from random import randint
l = []
for i in range(10):
k=[]
for j in range(10):
a= randint(1,100)
k.append(a)
l.append(k)
print(l)
print(max(l[2]))
b = []
for i in range(10):
a = l[i][5]
b.append(a)
print(min(b))
t = [ [0]*10 for i in [0]*10]
para cada elemento se creará un nuevo [0]*10
..
twod_list = [[foo for _ in range(m)] for _ in range(n)]
para n es el número de filas, y m es el número de columna, y foo es el valor.