Crear matrices bidimensionales y acceder a sub-matrices en Ruby

Me pregunto si existe la posibilidad de crear una matriz bidimensional y acceder rápidamente a cualquier subarranque horizontal o vertical en ella.

Creo que podemos acceder a una matriz secundaria horizontal en el siguiente caso:

x = Array.new(10) { Array.new(20) } x[6][3..8] = 'something' 

Pero, por lo que yo entiendo, no podemos acceder de esta manera:

 x[3..8][6] 

¿Cómo puedo evitar o piratear este límite?

Hay algunos problemas con los Arrays bidimensionales en la forma en que los implementa.

 a= [[1,2],[3,4]] a[0][2]= 5 # works a[2][0]= 6 # error 

Hash como Array

Prefiero usar Hashes para Arrays multidimensionales

 a= Hash.new a[[1,2]]= 23 a[[5,6]]= 42 

Esto tiene la ventaja de que no tiene que crear columnas o filas manualmente. Insertar en hashes es casi O (1) , por lo que no hay ningún inconveniente aquí, siempre y cuando su Hash no se vuelva demasiado grande.

Incluso puede establecer un valor predeterminado para todos los elementos no especificados

 a= Hash.new(0) 

Entonces ahora acerca de cómo obtener subarrays

 (3..5).to_a.product([2]).collect { |index| a[index] } [2].product((3..5).to_a).collect { |index| a[index] } 

(a..b).to_a ejecuta en O (n). Recuperar un elemento de un Hash es casi O (1), por lo que el recostackdor se ejecuta en casi O (n). No hay forma de hacerlo más rápido que O (n), ya que copiar n elementos siempre es O (n).

Hashes pueden tener problemas cuando se están haciendo demasiado grandes. Así que lo pensaría dos veces antes de implementar una Array multidimensional como esta, si supiera que mi cantidad de datos está creciendo.

 rows, cols = x,y # your values grid = Array.new(rows) { Array.new(cols) } 

En cuanto a los elementos de acceso, este artículo es bastante bueno para el paso a paso para encapsular una matriz en la forma que desee:

Cómo hacer ruby ​​array

No mencionaste tu objective real, pero tal vez esto pueda ayudar:

 require 'matrix' # bundled with Ruby m = Matrix[ [1, 2, 3], [4, 5, 6] ] m.column(0) # ==> Vector[1, 4] 

(y Vectors actúa como matrices)

o, usando una notación similar a la que desee:

 m.minor(0..1, 2..2) # => Matrix[[3], [6]] 

Aquí hay una caja de matriz 3D

 class Array3D def initialize(d1,d2,d3) @data = Array.new(d1) { Array.new(d2) { Array.new(d3) } } end def [](x, y, z) @data[x][y][z] end def []=(x, y, z, value) @data[x][y][z] = value end end 

Puede acceder a las subsecciones de cada matriz al igual que cualquier otra matriz de Ruby. @data [0..2] [3..5] [8..10] = 0, etc.

x.transpose[6][3..8] o x[3..8].map {|r| r [6]} x[3..8].map {|r| r [6]} daría lo que quiere.

Ejemplo:

 a = [ [1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15], [21, 22, 23, 24, 25] ] #a[1..2][2] -> [8,13] puts a.transpose[2][1..2].inspect # [8,13] puts a[1..2].map {|r| r[2]}.inspect # [8,13] 

Estoy bastante seguro de que esto puede ser muy simple

 2.0.0p247 :032 > list = Array.new(5) => [nil, nil, nil, nil, nil] 2.0.0p247 :033 > list.map!{ |x| x = [0] } => [[0], [0], [0], [0], [0]] 2.0.0p247 :034 > list[0][0] => 0 
 a = Array.new(Array.new(4)) 0.upto(a.length-1) do |i| 0.upto(a.length-1) do |j| a[i[j]] = 1 end end 0.upto(a.length-1) do |i| 0.upto(a.length-1) do |j| print a[i[j]] = 1 #It's not a[i][j], but a[i[j]] end puts "\n" end 

Aquí está la versión simple

  #one a = [[0]*10]*10 #two row, col = 10, 10 a = [[0]*row]*col 

Aquí hay una manera fácil de crear una matriz “2D”.

 2.1.1 :004 > m=Array.new(3,Array.new(3,true)) => [[true, true, true], [true, true, true], [true, true, true]]