Одна з головних цілей Julia - уміти швидко й ефективно виконувати обчислення над числовими даними. Багато числових даних.
Зазвичай дані зберігаються в масивах (або в якомусь спорідненому типі), тож цілком слушно сказати, що масиви лежать у самому серці мови Julia.
Масиви можуть бути довільного розміру (обмеженого лише обсягом памʼяті обладнання) і мати довільну кількість вимірів.
Цей вступний концепт зосереджується на основах одновимірних масивів, які називають векторами.
У Julia вектор - це впорядкована послідовність значень, доступ до яких можна отримати за номером індексу.
Найпростіший спосіб створити вектор - перелічити значення в квадратних дужках:
julia> num_vec = [1, 4, 9]
3-element Vector{Int64}:
1
4
9
julia> str_vec = ["arrays", "are", "important"]
3-element Vector{String}:
"arrays"
"are"
"important"
Тип Vector відповідає типу кожного елемента.
То вектори мають бути однорідними (усі елементи одного типу)?
Певною мірою так, і якщо ми хочемо найкращої продуктивності, варто до цього прагнути.
Однак Julia, коли потрібно, оминає це обмеження за допомогою типу Any:
julia> mixed_vector = [1, "str", 'c']
3-element Vector{Any}:
1
"str"
'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)
Коли ми створюємо порожній вектор, Julia типово використовує тип елементів Any, але його можна задати конкретніше, вказавши потрібний тип елементів для порожнього масиву.
julia> empty_vec = []
Any[]
julia> empty_int_vec = Int64[]
Int64[]
Прочитаймо це правило й запамʼятаймо його:
Це звично кожному, хто користувався іншими мовами для аналізу даних (R, Matlab, Fortran...), але може видатися шокуючим для фахівців із компʼютерних наук, які мають досвід роботи з мовами, схожими на C.
В іншому разі індекси працюють так, як неважко здогадатися: просто беремо їх у квадратні дужки:
squares = [0, 1, 4, 9, 16]
squares[1] # 0
squares[3] # 4
squares[begin] # 0 ("begin" is synonym for 1)
squares[end] # 16 ("end" is synonym for length(squares))
Звернімо увагу на зручність індексації за допомогою end (це дуже корисно) і begin (а це, мабуть, ні).
Програмісти Python можуть замислитися про відʼємні індекси.
Не варто: у Julia їх немає, і вони спричинять помилку BoundsError, як і будь-який індекс, менший за 1 або більший за length(squares).
Вектори в Julia змінювані: ми можемо змінювати вміст окремих елементів.
julia> vals = [1, 3, 5, 7]
4-element Vector{Int64}:
1
3
5
7
julia> vals[2] = 4 # reassign the value of this element
4
# Only the value at position 2 changes:
julia> vals
4-element Vector{Int64}:
1
4
5
7
Є чимало функцій для роботи з векторами, хоча документація Julia узагальнює їх до «колекцій», а не векторів.
Зауважмо, що за домовленістю функції, які змінюють свої вхідні дані, мають ! у назві.
Компілятор цього не перевіряє, але в світі Julia це дуже стійка домовленість.
Ось кілька корисних функцій:
push!().pop!().pushfirst!() і popfirst!().insert!() і deleteat!().julia> vals = [1, 3]
2-element Vector{Int64}:
1
3
julia> push!(vals, 5, 6) # can add multiple values
4-element Vector{Int64}:
1
3
5
6
julia> pop!(vals) # mutates vals, return popped value
6
julia> vals
3-element Vector{Int64}:
1
3
5
Як майбутня чарівниця, Еліз має потренувати дещо з основ. У неї є стос карток, яким вона хоче маніпулювати.
Щоб трохи спростити собі життя, вона використовує лише картки від 1 до 10, тож її стос карток можна подати як вектор чисел. Позиція певної картки відповідає індексу у векторі.
Щоб узяти картку, поверніть картку за індексом position із заданого стосу.
julia> stack = [1, 2, 4, 1];
julia> position = 3;
julia> get_item(stack, position)
4
Виконайте невеличкий фокус і обміняйте картку за індексом position на надану картку для заміни.
Поверніть змінений стос.
julia> stack = [1, 2, 4, 1];
julia> position = 3;
julia> replacement_card = 6;
julia> set_item!(stack, position, replacement_card)
[1, 2, 6, 1]
Змусьте картку зʼявитися, вставивши нову картку на верх стосу. Поверніть змінений стос.
julia> stack = [5, 9, 7, 1];
julia> new_card = 8;
julia> insert_item_at_top!(stack, new_card)
[5, 9, 7, 1, 8]
Змусьте картку зникнути, прибравши картку за вказаним індексом position зі стосу.
Поверніть змінений стос.
julia> stack = [3, 2, 6, 4, 8];
julia> position = 3;
julia> remove_item!(stack, position)
[3, 2, 4, 8]
Змусьте картку зникнути, прибравши картку згори стосу. Поверніть змінений стос.
julia> stack = [3, 2, 6, 4, 8];
julia> remove_item_from_top!(stack)
[3, 2, 6, 4]
Змусьте картку зʼявитися, вставивши нову картку в низ стосу. Поверніть змінений стос.
julia> stack = [5, 9, 7, 1];
julia> new_card = 8;
julia> insert_item_at_bottom!(stack, new_card)
[8, 5, 9, 7, 1]
Змусьте картку зникнути, прибравши картку з низу стосу. Поверніть змінений стос.
julia> stack = [8, 5, 9, 7, 1];
julia> remove_item_at_bottom!(stack)
[5, 9, 7, 1]
Перевірте, чи розмір стосу дорівнює stack_size, чи ні.
julia> stack = [3, 2, 6, 4, 8];
julia> stack_size = 4;
julia> check_size_of_stack(stack, stack_size)
false
Зареєструйтеся на Exercism, щоб вивчати й опановувати Julia, а також 35 концепцій128 вправ та справжнє наставництво від людей, і все це безкоштовно.