Ruby: ООП и вопрос о двухцветном массиве - PullRequest
0 голосов
/ 12 ноября 2009

Мне нужно создать двумерный массив Class. Я выполнил работу, но обнаружил, что у моего класса просто есть внутренний двухцветный массив, и для доступа к элементам мне нужно написать избыточное слово «таблица»:

class Table
  attr_accessor :table
  def initialize(w,h)
    @table = Array.new(h)
    h.times do @table << Array.new(w) 
  end
end

x = Table.new(10,10)
x.table[5][6] = 'example'

и так далее. Идея состоит в том, что я хочу написать только x[5][6] сразу, чтобы получить доступ к элементам. Насколько я понимаю, я должен унаследовать класс Array и каким-то образом расширить его, чтобы он вел себя как двумерный массив. Если я прав - как мне это сделать?

Ответы [ 3 ]

1 голос
/ 12 ноября 2009

Я думаю это может быть то, что вы ищете. Он использует переменную экземпляра @table для отслеживания внутреннего массива, но не предоставляет доступ к нему. Вот определение:

class Table

  def initialize(row_count, column_count)
    @table = Array.new

    row_count.times do |index|
      @table[index] = Array.new(column_count)
    end
  end

  def []=(row, column, value)
    @table[row][column] = value
  end

  def [](row, column = nil)
    if column.nil?
      @table[row]
    else
      @table[row][column]
    end
  end

  def inspect
    @table.inspect
  end
end

А вот как это можно использовать:

t = Table.new(2, 5)
t[0,0] = 'first'
t[1,4] = 'last'
t[0][1] = 'second'

puts t[0,0]
puts t.inspect

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

0 голосов
/ 12 ноября 2009

Есть ли какая-то конкретная причина, по которой вы хотели бы написать свой собственный класс массива? По умолчанию вы можете указать массиву, чем заполнять новые элементы, указав второй аргумент:

>> a = Array.new(10, [])
=> [[], [], [], [], [], [], [], [], [], []]

Редактировать: По-видимому, таким образом он заполняет массивы ссылками на переданный объект, поэтому после выполнения a[0][0] = "asd" каждый первый элемент содержащихся массивов изменится. Не круто.

>> a[0][0] = "asd"
=> "asd"
>> a
=> [["asd"], ["asd"], ["asd"], ["asd"], ["asd"], ["asd"], ["asd"], ["asd"], ["asd"], ["asd"]]

Чтобы каждый содержащийся массив был уникальным, используйте третий синтаксис и дайте ему блок для выполнения каждый раз - результат блока будет использоваться для заполнения массива:

>> b = Array.new(10) { [] }
=> [[], [], [], [], [], [], [], [], [], []]
>> b[0][0] = "asd"
=> "asd"
>> b
=> [["asd"], [], [], [], [], [], [], [], [], []]

Кроме того, из-за того, как работают массивы ruby, определение размера оси y даже не требуется:

>> a = Array.new(5)
=> [nil, nil, nil, nil, nil]
>> a[10]
=> nil
>> a[10] = "asd"
=> "asd"
>> a
=> [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, "asd"]

Массив автоматически расширяется, когда вы помещаете в индекс нечто большее, чем текущий размер. Итак, просто создайте массив, содержащий десять пустых массивов, и у вас будет готов массив для использования размером 10 * n.

0 голосов
/ 12 ноября 2009
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...