Чтение онлайн

на главную - закладки

Жанры

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

а = %w[Elrond Galadriel Aragorn Saruman Legolas]

b = a.min # "Aragorn"

с = a.max # "Saruman"

d = a.min {|x,y| x.reverse <=> y.reverse} # "Elrond"

e = a.max {|x,y| x.reverse <=> y.reverse} # "Legolas"

Чтобы найти индекс минимального или максимального элемента (в предположении, что такой элемент один), применяется метод

index
:

# Продолжение предыдущего примера...

i = a.index a.min # 2

j = a.index a.max # 3

Такую

же технику можно использовать и в других похожих ситуациях. Однако, если элемент не единственный, то будет найден только первый.

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. Нетривиальная задача — гарантировать, что строка случайно не окажется больше, чем положено.

8.1.8. Реализация разреженной матрицы

Иногда бывает нужен массив, в котором определена лишь небольшая часть элементов, а остальные не определены вовсе или (даже чаще) равны 0. Подобная разреженная матрица потребляет так много памяти зря, что были найдены способы более изощренной ее реализации.

Конечно, в большинстве случаев обычного массива Ruby вполне достаточно, так как в современных компьютерах недостатка памяти не ощущается. Элемент, которому не присвоено значение, будет равен

nil
, так что на его хранение расходуется всего несколько байтов.

С другой стороны, присваивание значения элементу массива, лежащему за текущей правой границей, приводит к созданию всех промежуточных элементов, причем они получают значение

nil
. Например, если определены элементы от 0 до 9 и затем производится присваивание элементу 1000, то создаются также элементы с индексами от 10 до 999, равные
nil
. Если это неприемлемо, надо поискать альтернативу.

В предлагаемом нами варианте массивы вообще не используются. Для реализации разреженной матрицы лучше подойдет хэш (за дополнительной информацией обратитесь к разделу 8.2.14).

Поделиться:
Популярные книги

Кубинский зал

Харрисон Колин
Детективы:
прочие детективы
6.40
рейтинг книги
Кубинский зал

Дважды одаренный. Том II

Тарс Элиан
2. Дважды одаренный
Фантастика:
городское фэнтези
альтернативная история
аниме
5.40
рейтинг книги
Дважды одаренный. Том II

Ночная музыка

Мойес Джоджо
Любовные романы:
современные любовные романы
8.64
рейтинг книги
Ночная музыка

100 великих войн

Соколов Борис Вадимович
100 великих
Справочная литература:
энциклопедии
6.40
рейтинг книги
100 великих войн

Скалолаз. В осаде

Стрэнтон Арч
29. Бестселлеры Голливуда
Детективы:
боевики
6.25
рейтинг книги
Скалолаз. В осаде

Неучтенный элемент. Том 10

NikL
10. Антимаг. Вне системы
Фантастика:
фэнтези
5.25
рейтинг книги
Неучтенный элемент. Том 10

Статьи

Переслегин Сергей Борисович
Документальная литература:
публицистика
5.00
рейтинг книги
Статьи

Любовь и магия (сборник)

Гаврилова Анна Сергеевна
Колдовские миры
Фантастика:
фэнтези
мистика
8.38
рейтинг книги
Любовь и магия (сборник)

Цикл романов "Целитель". Компиляция. Книги 1-17

Большаков Валерий Петрович
Целитель
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Цикл романов Целитель. Компиляция. Книги 1-17

Второгодка. Книга 2. Око за око

Ромов Дмитрий
2. Второгодка
Фантастика:
героическая фантастика
альтернативная история
фэнтези
5.00
рейтинг книги
Второгодка. Книга 2. Око за око

Вне закона

Брэнд Макс
Приключения:
вестерны
5.75
рейтинг книги
Вне закона

Пограничная застава

Думбадзе Нодар Владимирович
Проза:
военная проза
5.00
рейтинг книги
Пограничная застава

Во имя Ишмаэля

Дженна Джузеппе
Детективы:
политические детективы
5.00
рейтинг книги
Во имя Ишмаэля

Разгон

Загребельный Павел Архипович
Проза:
современная проза
5.00
рейтинг книги
Разгон