Как объявить двумерный массив в Ruby

мне нужен двумерный массив в Ruby, к которому я могу получить доступ, например, так:

if @array[x][y] == "1" then @array[x][y] = "0"

проблема в том, что я не знаю начальных размеров размеров массива, и я выращиваю массив (с помощью << оператор).

как объявить его как переменную экземпляра, поэтому я не получаю такой ошибки?

undefined method `[]' for nil:NilClass (NoMethodError)

ВОПРОС ОБНОВЛЕН:

@array = Array.new {Array.new} 

теперь работает для меня, поэтому комментарий от Мэтта ниже Правильный!

I просто выяснил, почему я получил ошибку, потому что я повторял массив следующим образом:

for i in 0..@array.length
    for j in 0..@array[0].length
        @array[i][j] ...

что было явно неправильно и привело к ошибке. Это должно быть так:

for i in 0..@array.length-1
        for j in 0..@array[0].length-1
            @array[i][j] ...

3 ответов


простая реализация для разреженного 2-мерного массива с использованием вложенных хэшей,

class SparseArray
  attr_reader :hash

  def initialize
    @hash = {}
  end

  def [](key)
    hash[key] ||= {}
  end

  def rows
    hash.length   
  end

  alias_method :length, :rows
end

использование:

sparse_array = SparseArray.new
sparse_array[1][2] = 3
sparse_array[1][2] #=> 3

p sparse_array.hash
#=> {1=>{2=>3}}

#
# dimensions
#
sparse_array.length    #=> 1
sparse_array.rows      #=> 1

sparse_array[0].length #=> 0
sparse_array[1].length #=> 1

комментарий Мэтта на ваш вопрос совершенно правильный. Однако, основываясь на том, что вы пометили это "conways-game-of-life", похоже, что вы пытаетесь инициализировать двумерный массив, а затем использовать его в расчетах для игры. Если вы хотите сделать это в Ruby, один из способов сделать это будет:

a = Array.new(my_x_size) { |i| Array.new(my_y_size) { |i| 0 }}

который создаст массив my_x_size * my_y_size, заполненный нулями.

этот код создает новый массив вашего размера x, а затем инициализируйте каждый элемент этого массива как другой массив вашего размера y и инициализируйте каждый элемент каждого второго массива с помощью 0.


Рубин Array не дает вам этой возможности.

либо вы делаете это вручную:

(@array[x] ||= [])[y] = 42

или вы используете хэш:

@hash = Hash.new{|h, k| h[k] = []}
@hash[42][3] = 42
@hash # => {42 => [nil, nil, nil, 42]}