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 的文件把它們一般化為「collection」,而不只是向量。
注意,依照慣例,會修改輸入的函式名稱會帶有 !。
編譯器不會強制執行這點,但這在 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
身為見習魔術師,Elyse 需要練習一些基本功。 她有一疊卡片,想要操作它們。
為了方便起見,她只用 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