Книга: Программирование на языке Ruby

8.1.7. Специализированные функции индексирования

8.1.7. Специализированные функции индексирования

Для отображения индексов на элементы массива интерпретатор языка пользуется функцией индексирования. Поскольку методы доступа к элементам массива можно переопределять, мы можем реализовать любой способ индексирования.

Например, ниже реализован массив, в котором индексы начинаются с 1, а не с нуля:

class Array2 < Array
 def [] (index)
  if index>0
   super(index-1)
  else
   raise IndexError
  end
 end
 def []=(index,obj)
  if index>0
   super(index-1,obj)
  else
   raise IndexError
  end
 end
end
x = Array2.new
x[1]=5
x[2]=3
x[0]=1  # Ошибка.
x[-1]=1 # Ошибка.

Отметим, что отрицательные индексы (от конца массива) здесь запрещены. Имейте в виду, что в реальной задаче придется внести и другие изменения, например переопределить метод slice и пр. Но общую идею вы поняли.

Аналогичный подход можно применить для реализации многомерных массивов (мы еще вернемся к ним в разделе 8.1.11).

Можно также реализовать нечто вроде треугольной матрицы, как показано ниже. Это частный случай двумерного массива, в котором элемент в позиции x,y совпадает с элементом в позиции y,x (поэтому хранить можно только один). Иногда это бывает полезно, например для хранения неориентированного графа (как мы покажем ближе к концу главы).

class TriMatrix
 def initialize
  @store = []
 end
 def [](x,y)
  if x > у
   index = (x*x+x)/2 + y
   @store[index]
  else
   raise IndexError
  end
 end
 def []=(x,y,v)
  if x > y
   index = (x*x+x)/2 + y
   @store[index] = v
  else
   raise IndexError
  end
 end
end
t = TriMatrix.new
t[3,2] = 1
puts t[3,2] # 1
puts t[2,3] # IndexError

В этом примере мы реализовали матрицу так, что номер строки должен быть больше или равен номеру столбца. Но можно было бы просто отобразить симметричные пары индексов на один и тот же элемент. Проектное решение зависит от предполагаемого способа использования матрицы.

Можно было унаследовать классу Array, но нам кажется, что наше решение понять легче. Формула индексирования довольно сложна, но десяти минут с карандашом и бумагой хватит, чтобы убедить любого в ее правильности. Чтобы сделать данный класс по-настоящему полезным, надо бы немного усовершенствовать его; оставляем вам это в качестве упражнения.

Кроме того, треугольную матрицу можно реализовать в виде массива, содержащего массивы, размер которых увеличивается по мере увеличения номера строки. Примерно так мы и поступили в разделе 8.1.11. Нетривиальная задача — гарантировать, что строка случайно не окажется больше, чем положено.

Оглавление книги

Оглавление статьи/книги

Генерация: 1.234. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз