# Массивы

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

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

```ruby
# способ создания массива
 # как можно увидеть, при создании мы перендаем сразу несколько значений
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
```

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

```ruby
int_arr = [1, 2, 3, 4]

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

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

```ruby
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`:

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

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

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

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

```ruby
# заранее созданный массив с 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


```

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

```ruby
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` или нет, что заметно усложнит структуру кода.

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

```ruby
    # Двумерный массив
    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(...)](https://blog.appsignal.com/2018/07/31/generating-random-numbers-in-ruby.html)
* При написании программы выносите 'магические числа' в отдельные переменные

```ruby
# Вообще не понятно что это за массив, что в нем находится
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.&#x20;

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

* LIST — выводит дела с их порядковыми номерами;
* ADD — добавляет дело в конец списка или дело на определённое место, сдвигая остальные дела вперёд, если указать номер;&#x20;
* EDIT — заменяет дело с указанным номером;
* DELETE — удаляет.

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

* LIST
* ADD Какое-то дело
* ADD 4 Какое-то дело на четвёртом месте
* EDIT 3 Новое название дела
* DELETE 7  Команды вводятся одной строкой пользователем в консоль.

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

* [Еще немного о массивах](https://www.rubyguides.com/2015/05/ruby-arrays/)
* [проверка на пустоту](https://www.bootrails.com/blog/ruby-nil-vs-blank-vs-empty-vs-presence/)
* [магическое число](https://ru.wikipedia.org/wiki/%D0%9C%D0%B0%D0%B3%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5_%D1%87%D0%B8%D1%81%D0%BB%D0%BE_\(%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5\))


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://evgenii-afanasev.gitbook.io/ruby-course/2_basics/7_arrays.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
