Массивы

Мы изучили базовые типы данных такие как Boolean, String, Integer и изучили последовательность Range. Давайте поговорим про базовую структуру данных - массив.

Массив (Array) - множество значений объединенных в одной структуре данных. По сути это структура, которая содержит в себе упорядоченное множество элементов. Это может быть массив строк, или массив чисел, а может включать и то и то. Хорошей практикой является хранить в массиве элементы одного и того же типа данных, так как часто приходится обрабатывать этот массив, а если в нем содержатся и строки и числа, то поведение программы поменяется. Пожалуй проще всего представлять массив на большую коробку, в которой есть набор маленьких коробок, внутри которых содержится значение

# способ создания массива
 # как можно увидеть, при создании мы перендаем сразу несколько значений
arr = Array.new(1, 2, 3, 4)

# Ранее мы работали с циклом на примере Range
# Но массив как и Range это лишь один из варианта реализации множества
for x in arr
  # В данном случае мы сначала распечатаем 1, потом 2, потом 3, потом 4
  puts x
end

# А этог упрощенный способ создания массивов
arr_simplify = [5, 6, 7, 8]

for x in arr_simplify
  # В данном случае мы сначала распечатаем 5, потом 6, потом 7, потом 8
  puts x
end

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

int_arr = [1, 2, 3, 4]

arr_length = int_arr.length # = 4, хотя индекс последнего элемента равен 3

Кроме того мы можем получать точечный доступ к нашим элементам по его индексу. Индекс - местоположение элемента по счету. Так как массив это упорядоченная структура данных, то элементы расположены строго в том порядке, в каком они были добавлены. Важно индекс массива начнается с 0, а не с 1 как это можно подумать.

arr_for_getting_by_index = [84312, 2354, 66, 12, 9]

first_element = arr_for_getting_by_index[0] # = 84312, так как это первый элемент, а значит индекс 0
second_element = arr_for_getting_by_index[1] # = 2354, так как это второй элемент, а значит индекс 1

# В данном случае мы создали цикл не для значений массива, а для его индексов, учитывая, что длина массива всегда на +1 больше индексма последнего элемента
for index in (0..arr_for_getting_by_index.length - 1)
    puts "element of array by index = #{index} is #{arr_for_getting_by_index[index]}"
end

Можно подумать, что примеров использования у массива не так много, но давайте посмотрим на пример конструкции (метода) .split у String:

    # наша исходная фраза
    welcome = 'You are welcome'
    # .split(delimeter) - консрукция (метод) разбиения строки на массив слов по определенному правилу переданному в его аргументы
    # В данном примере мы в качестве аргумента передаем строку состоящую из 1 пробела. 
    # В метод также можно передавать регулярное выражение, но эту тему мы изучим в дальнейших уроках
    words = welcome.split(' ') # = ['You', 'are', 'welcome']

Даже если пойти немного глубже, то можно выяснить, что сама по себе строка это всего лишь массив симолов и работать мы можем с ней точно также как и с массивом

    characters = 'Example'
    puts characters[0] # = E
    
    # с помощью цикла мы обходим каждую букву слова на каждый цикл
    for char in characters
        puts char # сначала будет буква E, потом x, потом a и тд.
    end

Также массив это изменяемая структура. Мы можем добавлять новые элементы, изменять значения, удалять элементы.

# заранее созданный массив с 3 элементами
source_arr = [1, 2, 3]
# пустой массив
target_arr = []

# циклом обходим все индексы массива
for index in (0..source_arr.length)
    # .push(element) позволяет нам добавить в массив новые элементы
    # в данном случае мы добавляем поочередно значения из source_arr по индексу
    target_arr.push(source_arr[index])
    # .delete(index) позволяет удалять наши элементы по его индексу
    source_arr.delete(index)
end

puts "source array: #{source_arr}" # = []. как можем увидеть, наш изначальный массив стал пустым
puts "target array: #{target_arr}" # = [1, 2, 3]. а наш пустой массив содержит в таком же порядке элементы из исходного массива

# вспоминаем совет про маленькие коробки внутри большой коробки
# В данном случае мы кладем в малеьнкую коробку по индексу новое значение, затирая старое
target[0] = 9 

puts "target array: #{target_arr}" # =  [9, 2, 3]

# а теперь попробуем изменить индекс, которого не существует в массиве
target[10] = 87

А что будем если изменить индекс, которого не существует ?

arr = [0, 9, 8]

# p позволяет нам иследовать полностью внутренность массива, а не просто красиво его распечатать в консоли
# подробнее про этот метод говорилось в доп. материале 1_prepare/4_first_program
p target_arr # = [0, 9, 8]
puts target_arr.length # = 3
arr[10] = 87

# может показаться, что добавился просто элемент, но нет
puts target_arr.inspect # =  [0, 9, 8, nil, nil, ... , 87]
# На самом деле наш массив увеличил размер до своего последнего индекса, а все достающие элементы заполнил nil
puts target_arr.length # = 11

Старайтесь аккуратнее работать с массивом на уровне индексов, так как в последующем при обработке массива придется лишний раз проверять является ли элемент nil или нет, что заметно усложнит структуру кода.

Как мы помним массив может содержать любые значения в себе, в том числе и сам массив или любую другую структуру данных, как и любая другая структура данных может хранить в себе массив. Массив, который содержит себе вложенный массив называется двумерным, массив, который состоит из массивов, которые состоят из массивов называется трехмерный и тд.

    # Двумерный массив
    arr_in_arr = [[0, 1], [16, 4], [98, 12]]

Задание reverse

  • Получите из консоли введенную пользователем строку и разбейте ее на массив слов

  • разверните массив в обратную сторону

  • *Реализуйте 2 пункт с помощью инструментов из урока не прибегая к использованию новых

Пример:

Hello world -> [Hello, world] -> [world, Hello]

Задание med_clinic

  • Создайте массив типа Float с температурами 30 пациентов (от 32 до 40 градусов).

  • Напишите код, который выводит среднюю температуру по больнице и количество здоровых пациентов (с температурой от 36,2 до 36,9), а также температуры всех пациентов.

Рекомендации:

  • Помним про rand(...)

  • При написании программы выносите 'магические числа' в отдельные переменные

# Вообще не понятно что это за массив, что в нем находится
for x in [23, 30, 15, 90, 11]
  # непонятно что это ха число 21, для чего мы это делаем
  if x > 21
    puts x
  end
end 

# теперь у нас есть представление что это за цифры хотя бы
user_ages = [23, 30, 15, 90, 11]
# и что это за число
limit_age = 21

# не зная точно какое задание выполнялось мы уже можем понять, что мы обходим возраст пользователей
for age in user_ages
  # и если возраст больше лимита
  if age > limit_age
    # то мы его пропускаем и печатаем
    puts age
  end
end 

Задание cross

Создайте с помощью циклов двумерный массив строк. При его распечатке в консоли должен выводиться крестик из X:

    x     x
     x   x
      x x
       x
      x x
     x   x
    x     x

Задание todo_list

Разработайте список дел, который управляется командами в консоли. Команды: LIST, ADD, EDIT, DELETE.

Принцип работы команд:

  • LIST — выводит дела с их порядковыми номерами;

  • ADD — добавляет дело в конец списка или дело на определённое место, сдвигая остальные дела вперёд, если указать номер;

  • EDIT — заменяет дело с указанным номером;

  • DELETE — удаляет.

Примеры команд

  • LIST

  • ADD Какое-то дело

  • ADD 4 Какое-то дело на четвёртом месте

  • EDIT 3 Новое название дела

  • DELETE 7 Команды вводятся одной строкой пользователем в консоль.

Дополнительный материал

Last updated