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

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

Жанры

Программирование на языке 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).

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

Франкенштейн: Антология

Шелли Мэри
1. Лучшее
Фантастика:
социально-философская фантастика
научная фантастика
ужасы и мистика
7.43
рейтинг книги
Франкенштейн: Антология

Суперфрикономика

Левитт Стивен Д.
Научно-образовательная:
прочая научная литература
6.25
рейтинг книги
Суперфрикономика

Симеон Гордый

Балашов Дмитрий Михайлович
4. Государи московские
Научно-образовательная:
история
7.89
рейтинг книги
Симеон Гордый

Вечный. Книга VI

Рокотов Алексей
6. Вечный
Фантастика:
рпг
фэнтези
5.00
рейтинг книги
Вечный. Книга VI

Замок (сборник)

Вилсон Фрэнсис Пол
Мастера остросюжетного романа
Фантастика:
мистика
5.00
рейтинг книги
Замок (сборник)

Кодекс Крови. Книга ХVIII

Борзых М.
18. РОС: Кодекс Крови
Фантастика:
попаданцы
аниме
фэнтези
5.25
рейтинг книги
Кодекс Крови. Книга ХVIII

Религия и этика в изречениях и цитатах. Справочник

Душенко Константин Васильевич
Религия и эзотерика:
религия
5.00
рейтинг книги
Религия и этика в изречениях и цитатах. Справочник

Сочинения

Брюсов Валерий Яковлевич
Проза:
русская классическая проза
5.00
рейтинг книги
Сочинения

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

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

Арбан Саеш. Трилогия

Малицкий Сергей Вацлавович
50. В одном томе
Фантастика:
фэнтези
8.17
рейтинг книги
Арбан Саеш. Трилогия

Белый ферзь

Измайлов Андрей
Детективы:
прочие детективы
боевики
5.00
рейтинг книги
Белый ферзь

Вечный. Книга I

Рокотов Алексей
1. Вечный
Фантастика:
боевая фантастика
попаданцы
рпг
5.50
рейтинг книги
Вечный. Книга I

Реликварий

Престон Дуглас
2. Пендергаст
Фантастика:
ужасы и мистика
7.00
рейтинг книги
Реликварий

Нью-Йорк

Резерфорд Эдвард
The Big Book
Проза:
историческая проза
6.00
рейтинг книги
Нью-Йорк