Pregunta

Me enfrento a algo que no entiendo completamente.

Tengo una matriz cuyos elementos son matrices.

Así que tengo dos bucles anidados, en el bucle interno llené mi matriz interior y luego en el bucle exterior llené la matriz externa con la matriz interna.

arr=[]
mat=[]
for m in (0..1)
  for k in (0..1)
    arr[k]=rand.to_s
  end
  mat[m]=arr
end

Al final, mi matriz está llena de dos matrices; Cada matriz contiene los valores calculados en la última iteración. Si quiero que el primer elemento en Matrix contenga la primera matriz calculada, tengo que reiniciar el objeto ARR en cada bucle. Entonces parece que la asignación se realiza por referencia hasta que el objeto ARR esté "limpiado". Si agrego

mat[m]=arr
arr=[]

Todos los funcionan como se esperaba: MAT [0] contendrá la matriz calculada en el primer bucle, y MAT [1] contendrá la matriz calculada en el segundo bucle.

¿Es esto por diseño o es un efecto secundario no deseado? Esto está sucediendo solo si asigno matrices como elementos de matriz. Si si llene una matriz con variables de cadena simples en un bucle, todo va como se esperaba.

Sé que es una buena práctica de programación para evitar reutilizar objetos, pero este comportamiento es de alguna manera extraño.

¿Fue útil?

Solución

Su problema es que el contenido de su variable ARR se está sobrescribiendo con cada iteración: el arr[k] sobrescribe lo que ya esté allí. La variable ARR debe ser local en el bloque: en su lugar:

mat = []
2.times do             # avoid for... use iterators instead
  row = []
  2.times do 
    row << rand.to_s
  end
  mat << row
end

Otros consejos

Me gusta el enfoque de Uso de hashes en lugar de matrices multidimensionales.

Qué tal esto:

def creat­e_matrix x, y, conte­nt = nil, &block
  rows = (0...x­).to_a
  cols = (0...y­).to_a
  indices = rows.­product cols
  matrix = {}
  indices.ea­ch { |inde­x| matri­x[index] = ( block­_given? ? yield­( index ) : conte­nt ) }
  matrix
end

Entonces hazlo:

matrix = create_matrix( 2, 2 ) { rand.to_s }

Obtendrá un hash, al que puede acceder así:

matrix[[0, 1]] #note the double brackets

Otra forma de hacerlo:

(1..4).map{rand}.each_slice(2).to_a
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top