Когда вы это закончите, сделайте перерыв! Вы уже многое изучили. Поздравляю! Вас удивляет, сколько разных вещей вы можете заставить делать компьютер? Ещё несколько глав, и вы сможете запрограммировать почти всё, что угодно. Серьёзно! Только взгляните на все эти штуки, что вы можете делать сейчас и которые не смогли бы сделать без циклов и ветвления.
А теперь давайте изучим новую разновидность объектов, которые отвечают за списки других объектов: массивы.
7. Массивы и итераторы
Давайте напишем программу, которая просит нас ввести сколько угодно слов (по одному слову в строке до тех пор, пока мы не нажмём Enter на пустой строке) и которая затем повторяет нам эти слова в алфавитном порядке. Идёт?
Так… сначала мы – ээ… ну… хммм… Хорошо, мы могли бы – ээ… ну…
Вы знаете, я не думаю, что мы сможем это сделать. Нам нужен способ хранить неизвестное количество слов и как-то держать их все вместе, чтобы они не смешивались с другими переменными. Нам нужно поместить их все в какое-то подобие списка. Нам нужны массивы.
Массив – это просто список в вашем компьютере. Каждая ячейка в списке ведёт себя как переменная: вы можете посмотреть, на какой объект указывает определённая ячейка, и вы можете сделать так, чтобы она указывала на другой объект. Давайте посмотрим на некоторые массивы:
[]
#
пустой массив
[5]
#
массив из одного числа
['Привет'
, 'До свидания']
#
массив из 2–х строк
flavor =
'ванильный'
#
Это не массив, конечно…
[89.9, flavor,[true, false]]
#
…но это – массив.
Итак, сначала у нас есть пустой массив, затем массив, содержащий единственное число, затем массив, содержащий две строки. Потом у нас имеется простое присваивание; затем – массив, содержащий три объекта, последний из которых — это массив [true, false]. Помните, что переменные – это не объекты, поэтому наш последний массив в действительности указывает на число с плавающей точкой, на строку и на массив. Даже если бы мы сделали, чтобы переменная flavor указывала на что-нибудь другое, это не изменило бы этот массив.
Чтобы помочь нам с поиском конкретных объектов в массиве, каждой ячейке даётся номер – индекс. Программисты (и, по случайному совпадению, большинство математиков) начинают считать их с нуля, так что первая ячейка в массиве – это ячейка номер ноль. Вот как мы должны адресоваться к объектам в массиве:
names =['Ада',
'Белль',
'Крис']
puts names
puts names[0]
puts names[1]
puts names[2]
Ада
Белль
Крис
Ада
Белль
Крис
nil
Итак, мы видим, что puts names выводит каждое имя в массиве names. Затем мы используем puts names[0], чтобы напечатать «первое» имя в массиве и puts names[i], чтобы напечатать «второе»… Уверен, что это кажется запутанным, но вы непременно привыкните к этому. Вы просто должны действительно начать думать, что отсчёт начинается с нуля, и перестать использовать такие слова, как «первый» и «второй». Если вы идёте на обед из пяти блюд, не говорите о «первом» блюде; говорите о блюде ноль (а у себя в голове думайте о course[0]). На правой руке у вас пять пальцев с номерами 0, 1, 2, 3 и 4. Моя жена и я умеем жонглировать. Когда мы жонглируем шестью булавами, мы жонглируем булавами 0-5. Надеемся, что через несколько месяцев мы сможем жонглировать булавой номер 6 (и таким образом будем жонглировать между собой семью булавами). Вы поймёте, что привыкли к этому, когда начнёте использовать слово «нулевой». :-) Да, в самом деле есть такое слово: спросите у любого программиста или математика.
Наконец, мы попытались выполнить puts names[3], просто чтобы посмотреть, что же получится. Вы ожидали ошибку? Иногда, когда вы задаёте вопрос, ваш вопрос не имеет смысла (по крайней мере для вашего компьютера); и тогда вам выдаётся ошибка. Иногда, однако, вы можете задать вопрос и ответ на него будет: ничего. Что в ячейке номер три? Ничего. Что в names[3]? nil: таким способом Ruby говорит «ничего». nil – это особенный объект, который обычно означает «никакой из объектов».
Если вся эта смешная нумерация ячеек массивов начинает вас «доставать», не бойтесь! Часто мы сможем обойтись совершенно без неё, используя различные методы массивов, как вот этот:
each позволяет нам делать что-нибудь (всё, что мы хотим) с каждым объектом, на который указывает массив. Так, если мы хотим сказать что-либо приятное о языке в приведённом ниже массиве, мы сделаем так:
languages = ['английский', 'немецкий', 'Ruby'] languages.each do |lang|
puts 'Мне нравится ' + lang + '!'
puts 'А вам?' end
puts 'А теперь давайте послушаем мнение о C++!' puts '…'
Мне нравится английский!
А вам?
Мне нравится немецкий!
А вам?
Мне нравится Ruby!
А вам?
А теперь давайте послушаем мнение о C++!