Julia 的核心目標之一,就是能夠快速又有效率地對數值資料進行計算。 _大量_的數值資料。
通常,這些資料會儲存在陣列(或某個相關型別)中,所以說陣列是 Julia 語言的核心,一點也不為過。
陣列的大小可以是任意的(只受限於硬體的記憶體限制),維度也可以任意多。
有些型別的陣列有特別的名稱(沿用線性代數的說法)。
一維陣列稱為 Vector,二維陣列稱為 Matrix。
在 Julia 中,這兩者都是 Array 的子型別。
這個入門概念著重於向量的基礎。 更高維度的陣列會在課程大綱稍後的部分介紹。
在 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"
向量的型別會與每個元素的型別相符。
嚴格來說,它是個_行_向量,但如果你不熟悉線性代數,現在請先忽略這一點。 等讀過多維陣列的概念之後,應該就會更清楚了。
所以向量必須是同質的(所有元素都是同一種型別)?
某種程度上,是的。而且如果你想要最好的效能,建議就朝這個方向努力。
不過,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[]
從全為 0 或全為 1 的向量開始,是很常見的做法。為此,有一些函式(不意外地)叫做 zeros() 和 ones(),它們以向量大小作為參數。
預設型別是 Float64,但也可以選擇指定其他數值型別。
以此類推,fill() 函式同時接受要重複的值,以及想要的向量大小。
julia> zeros(3)
3-element Vector{Float64}:
0.0
0.0
0.0
julia> ones(3)
3-element Vector{Float64}:
1.0
1.0
1.0
julia> ones(Int64, 3)
3-element Vector{Int64}:
1
1
1
julia> fill(42, 3)
3-element Vector{Int64}:
42
42
42
還有許多其他選項:請參閱手冊。
請閱讀並記住這條規則:
用過其他資料科學語言(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 的文件把它們一般化為「collections」,而不是向量。
請注意,依照慣例,會改變輸入內容的函式,名稱中會帶有 !。
編譯器不會強制執行這點,但在 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
向量的串接相當簡單,不過翻一下手冊就會發現,一旦考慮到多維陣列,還有複雜的地方等著我們。
append!() 函式可以接受好幾個向量和單一元素的混合輸入。
julia> append!([1, 2], [3, 4], [-1, -2], 15)
7-element Vector{Int64}:
1
2
3
4
-1
-2
15