Julia 的一个核心目标,就是能够快速、高效地对数值数据进行计算。 _海量_的数值数据。
通常,这些数据会存放在数组(或某种相关的类型)中,所以完全可以说,数组是 Julia 语言的核心。
数组可以有任意大小(仅受硬件内存的限制),也可以有任意多的维度。
这篇入门概念聚焦于一维数组的基础知识,在 Julia 中,一维数组称为 Vector。
在 Julia 中,Vector 是一个有序的值序列,可以通过下标访问其中的值。
创建 Vector 最简单的方法,就是把各个值写进方括号里:
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 的类型与每个元素的类型一致。
那么 Vector 必须是同质的(所有元素类型相同)吗?
从某种意义上说,是的,而且如果你追求最佳性能,建议尽量做到这一点。
不过,在必要时,Julia 可以借助Any类型绕过这一限制:
julia> mixed_vector = [1, "str", 'c']
3-element Vector{Any}:
1
"str"
'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)
创建空 Vector 时,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 中的 Vector 是_可变的_:我们可以修改单个格子里的内容。
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
有很多函数可以用来操作 Vector,不过 Julia 文档把它们泛化成了“集合”,而不只是 Vector。
注意,按照惯例,会修改输入的函数,名字里都带一个!。
编译器不会强制这一点,但这是 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