• Deque
— изменяемый и упорядоченный список элементов, предназначенный для использования либо в виде структуры стека (FIFO, или First In First Out), либо в качестве структуры очереди (FILO, или First In Last Out). Он оптимизирован для быстрой вставки и удаления на обоих концах.
Далее давайте подробнее рассмотрим некоторые из этих типов контейнеров.
Массивы и кортежи
Вы можете выразить некоторые простые данные с помощью чисел и текста, но вам быстро понадобится собрать больше информации в списки. Для этого вы можете использовать массивы и кортежи. Массив — это динамический контейнер, который может увеличиваться, сжиматься и изменяться во время выполнения программы. С другой стороны, кортеж статичен и неизменяем; его размер и типы элементов известны и фиксируются во время компиляции:
numbers = [1, 2, 3, 4] # This is of type Array(Int32)
numbers << 10
puts "The #{numbers.size} numbers are #{numbers}"
# => The 5 numbers are [1, 2, 3, 4, 10]
С массивами нельзя смешивать разные типы, если они не были указаны при создании массива. Эти ошибки обнаруживаются во время сборки; они не являются исключениями во время выполнения. Посмотрите это, например:
numbers << "oops"
# Error: no overload matches 'Array(Int32)#<<' with type String
Используя типы объединения, вы можете иметь массивы, в которых сочетаются более одного типа, либо инициализируя их несколькими типами, либо явно указывая их. Вот пример:
first_list = [1, 2, 3, "abc", 40]
p typeof(first_list) # => Array(Int32 | String)
first_list << "hey!" # Ok
# Now all elements are unions:
element = first_list[0]
p element # => 1
p element.class # => Int32
p typeof(element) # => Int32 | String
# Types can also be explicit:
second_list = [1, 2, 3, 4] of Int32 | String
p typeof(second_list) # => Array(Int32 | String)
second_list << "hey!" # Ok
# When declaring an empty array, an explicit type is mandatory:
empty_list = [] of Int32
Внутри массива все значения имеют один и тот же тип; значения разных типов при необходимости расширяются до объединения типов или общего предка. Это важно, поскольку массивы изменяемы, и значение по заданному индексу можно свободно заменить чем-то другим.
Тип Array
реализует стандартные модули Indexable
, Enumerable
и Iterable
, предоставляя несколько полезных методов для исследования коллекции и управления ею.
Кортеж похож на массив в том смысле, что он хранит ряд элементов в упорядоченном виде. Два основных различия заключаются в том, что кортежи являются неизменяемыми после их создания и что исходный тип каждого элемента сохраняется без необходимости объединения:
list = {1, 2, "abc", 40}
p typeof(list) # => Tuple(Int32, Int32, String, Int32)
element = list[0]
p typeof(element) # => Int32
list << 10 # Invalid, tuples are immutable.
Поскольку кортежи неизменяемы, они используются не так часто, как массивы.
И массивы, и кортежи имеют несколько полезных методов. Вот некоторые из наиболее распространенных: