假設你想要取得所有不超過 1000 的非負整數。 如果得把這些數字一個個打進陣列裡,那也太荒謬了。
為此我們有 range 型態:
julia> 0:1000
0:1000
julia> typeof(0:1000)
UnitRange{Int64}
範圍非常常見:不只是為了省下你打字的功夫,也常被用作函式的回傳型態。
注意,範圍_不是_陣列。
陣列在建立時就定義完成(「貪婪」求值),而且需要與陣列長度成正比的儲存空間。
相對地,範圍只是一組用來產生序列的指令(「惰性」求值,或稱「疊代器」)。
如果你需要把範圍當成陣列使用,可以用collect()函式來轉換:
julia> collect(0:5)
6-element Vector{Int64}:
0
1
2
3
4
5
你也可以選擇使用collect(type, range)來指定輸出陣列的型態。
也可以指定步長,這裡是 0.3:
julia> collect(1.0:0.3:2.0)
4-element Vector{Float64}:
1.0
1.3
1.6
1.9
所以語法是 start:stepsize:stop。
前後兩端的界限都是_包含_在內的,就像前面整數的例子那樣。
如果步長沒辦法整除 stop - start,最後一個元素也不會超過 stop。
如果想要更精細的控制,可以使用Base.range()函式,它提供了更多選項。
非數值的序列也可以用在範圍裡。 最簡單的例子是 ASCII 字母:
julia> 'a':'d'
'a':1:'d'
julia> typeof('a':'d')
StepRange{Char, Int64}
julia> collect('a':'d')
4-element Vector{Char}:
'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)
'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)
'd': ASCII/Unicode U+0064 (category Ll: Letter, lowercase)
Char 型態之後會在其他概念裡有更詳細的介紹。
現在只要把它們當成用單引號括起來的單一字元就好。
用first()和last()檢查範圍的界限。
判斷某個特定的值是否屬於某個範圍,通常很有用。
背後所用的函式是 in(),但更常見的是使用中綴運算子 in,或是它在數學上更常見的同義符號 ∈。
在合適的編輯器裡,輸入 ∈ 的快捷鍵是先打 \in 再按 Tab。
r = 1:10 # => 1:10
first(r) # => 1
last(r) # => 10
7 in r # => true
11 ∈ r # => false
這裡的 in 或 ∈ 運算子用在範圍上,但也可以用在向量、集合和字典等其他幾種集合型態上。
整數範圍和陣列都可以用在陣列索引裡:
nums = collect(10.0:50.0)
nums[3:2:7] # gives [12.0, 14.0, 16.0]
nums[ [3, 5, 7] ] # also gives [12.0, 14.0, 16.0]
搭配 end 使用也可以,不過因為運算子優先順序的關係,可能需要加上括號:
nums[(end - 3):end]
4-element Vector{Float64}:
47.0
48.0
49.0
50.0
當然,索引裡的任何一個元素都可以是已經存在的整數變數。