Create two-dimensional arrays and access submatrices in Ruby

I wonder if it is possible to create a two-dimensional array and quickly get access to any horizontal or vertical sub-option?

I believe that we can access the horizontal helper array in the following case:

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

But as I understand it, we cannot access it like this:

 x[3..8][6] 

How can I escape or hack this limit?

+62
arrays ruby multidimensional-array
Nov 12 '09 at 9:12
source share
9 answers

There are some problems with the 2-dimensional Arrays way to implement them.

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

Hash like Array

I prefer to use Hashes for multidimensional Arrays

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

This has the advantage that you do not need to manually create columns or rows. The hash insert is almost O (1) , so there is no shortage here if your Hash does not get too big.

You can even set a default value for all items not specified

 a= Hash.new(0) 

So, now on how to get 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 works in O (n). Getting an element from Hash is almost O (1), so the collection is done in almost O (n). It is impossible to do this faster than O (n), since copying n elements is always equal to O (n).

Hashes can have problems when they get too big. So I would think twice about implementing a multidimensional Array , like this, if I knew that my data volume was becoming large.

+83
Nov 12 '09 at 11:54
source share
 rows, cols = x,y # your values grid = Array.new(rows) { Array.new(cols) } 

Regarding access to elements, this article is pretty good for a phased way of encapsulating an array the way you want:

Like a ruby โ€‹โ€‹array

+29
Nov 12 '09 at 9:19
source share

You have not indicated your actual purpose, but perhaps this may help:

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

(and vectors act like arrays)

or using the same notation you want:

 m.minor(0..1, 2..2) # => Matrix[[3], [6]] 
+29
Nov 12 '09 at 12:29
source share

Here is the case of a three-dimensional array

 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 

You can access the subsections of each array just like any other Ruby array. @data [0..2] [3..5] [8..10] = 0, etc.

+9
Jul 14 '10 at 20:32
source share

x.transpose[6][3..8] or x[3..8].map {|r| r [6]} x[3..8].map {|r| r [6]} will give what you want.

Example:

 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] 
+5
Nov 12 '09 at 9:46
source share

I'm sure it can be very 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 
+1
Oct 17 '13 at 19:42 on
source share
 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 not a[i][j], but a[i[j]] end puts "\n" end 
0
Feb 14 '13 at 17:00
source share

Here is a simple version

  #one a = [[0]*10]*10 #two row, col = 10, 10 a = [[0]*row]*col 
-one
Jan 23 '13 at 5:39
source share

Here is an easy way to create a 2D array.

 2.1.1 :004 > m=Array.new(3,Array.new(3,true)) => [[true, true, true], [true, true, true], [true, true, true]] 
-3
Jul 27 '14 at 3:11
source share



All Articles