Создайте двумерные массивы и подматрицы доступа в Ruby
Интересно, есть ли возможность создать двухмерный массив и быстро получить доступ к любому горизонтальному или вертикальному подварианту?
Я считаю, что мы можем получить доступ к горизонтальному вспомогательному массиву в следующем случае:
x = Array.new(10) { Array.new(20) }
x[6][3..8] = 'something'
Но насколько я понимаю, мы не можем получить к нему доступ так:
x[3..8][6]
Как я могу избежать или взломать этот предел?
Ответы
Ответ 1
Есть некоторые проблемы с 2-мерным Arrays
способом их реализации.
a= [[1,2],[3,4]]
a[0][2]= 5 # works
a[2][0]= 6 # error
Hash
как Array
Я предпочитаю использовать Hashes
для многомерного Arrays
a= Hash.new
a[[1,2]]= 23
a[[5,6]]= 42
Это имеет то преимущество, что вам не нужно вручную создавать столбцы или строки. Вставка в хэши почти O (1), поэтому здесь нет недостатка, если ваш Hash
не становится слишком большим.
Вы даже можете установить значение по умолчанию для всех не указанных элементов
a= Hash.new(0)
Итак, теперь о том, как получить подмассивы
(3..5).to_a.product([2]).collect { |index| a[index] }
[2].product((3..5).to_a).collect { |index| a[index] }
(a..b).to_a
работает в O (n). Получение элемента из Hash
составляет почти O (1), поэтому сбор выполняется в почти O (n). Невозможно сделать это быстрее, чем O (n), так как копирование n элементов всегда равно O (n).
Hashes
могут иметь проблемы, когда они становятся слишком большими. Поэтому я бы дважды подумал о реализации многомерного Array
, как это, если бы я знал, что мой объем данных становится большим.
Ответ 2
rows, cols = x,y # your values
grid = Array.new(rows) { Array.new(cols) }
Что касается доступа к элементам, эта статья довольно хороша для поэтапного способа инкапсуляции массива так, как вы хотите:
Как рубиновый массив
Ответ 3
Вы не указали свою фактическую цель, но, возможно, это может помочь:
require 'matrix' # bundled with Ruby
m = Matrix[
[1, 2, 3],
[4, 5, 6]
]
m.column(0) # ==> Vector[1, 4]
(и векторы действуют как массивы)
или, используя аналогичную нотацию, которую вы желаете:
m.minor(0..1, 2..2) # => Matrix[[3], [6]]
Ответ 4
Здесь случай трехмерного массива
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
Вы можете получить доступ к подразделам каждого массива точно так же, как и любой другой массив Ruby.
@data [0..2] [3..5] [8..10] = 0
и т.д.
Ответ 5
x.transpose[6][3..8]
или x[3..8].map {|r| r [6]}
даст то, что вы хотите.
Пример:
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]
Ответ 6
Я уверен, что это может быть очень просто
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
Ответ 7
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
Ответ 8
Вот простая версия
#one
a = [[0]*10]*10
#two
row, col = 10, 10
a = [[0]*row]*col
Ответ 9
Вот простой способ создания массива "2D".
2.1.1 :004 > m=Array.new(3,Array.new(3,true))
=> [[true, true, true], [true, true, true], [true, true, true]]