Tuple在許多方面和Vector(一維array)很像。不過,兩者之間還是有幾個重要的差異。
( )而不是方括號[ ]來書寫,不過在意義明確的情況下,小括號可以省略。不可變性能讓編譯器進行更多最佳化,也讓元組的效能比向量更好,所以在不需要可變性的情況下,應該優先選用元組。
julia> t = (3, 5.2, "xyz")
(3, 5.2, "xyz")
# Non-homogeneous:
julia> dump(t)
Tuple{Int64, Float64, String}
1: Int64 3
2: Float64 5.2
3: String "xyz"
julia> t[2]
5.2
# Immutable:
julia> t[2] = 7.3
ERROR: MethodError: no method matching setindex!(::Tuple{Int64, Float64, String})
另外還有Tuple()建構子,可以把任何可迭代的集合轉換成元組。很方便的是,它會把字串視為由字元組成的可迭代集合。
julia> Tuple("Julia")
('J', 'u', 'l', 'i', 'a')
對任何元組來說,都可以透過索引存取元素,也可以對它執行迴圈。
任何純數值的元組也能用在sum()之類的數學函式裡,就跟陣列一模一樣。
元組可以透過多重賦值解構成個別元素。對於不需要的元素,可以用底線_當作虛擬變數。
julia> tup = (1, "Julia", true)
(1, "Julia", true)
julia> num, name, _ = tup
(1, "Julia", true)
julia> uppercase(name), 2num
("JULIA", 2)
寫過 Python 的人對這種多重賦值的語法一定很熟悉。
Tuple只包含值。NamedTuple則會把每個值和一個名稱配成對。
之後就可以用「點」記法存取個別的欄位:
julia> nt = (a = 1, b = 7.3)
(a = 1, b = 7.3)
julia> dump(nt)
@NamedTuple{a::Int64, b::Float64}
a: Int64 1
b: Float64 7.3
julia> nt.b
7.3
名稱在內部是以Symbol儲存的(一種不可變的型別,前面會加上冒號:),所以還有另一種語法可以用:
julia> nt[:b]
7.3
要分別取得名稱(也稱為「鍵」)或值都很容易:
julia> nt
(a = 1, b = 7.3)
julia> keys(nt)
(:a, :b)
julia> values(nt)
(1, 7.3)
請注意,對具名元組進行疊代只會產生_值_,而_名稱_會被忽略。
元組(無論是否具名)是把結構化資料傳入函式、從函式傳出的常見做法。在這種用途下,不可變性很有好處,既能確保資料安全,也能讓編譯器進行更積極的最佳化。
Azara 和 Rui 是同隊隊友,正在參加一場海盜主題的尋寶比賽。 其中一人手上有一份附著地圖座標的寶物清單,另一人則有一份附著地圖座標的地點名稱清單。 他們還拿到了空白地圖,上頭的起點標示著「你在這裡」。
| Azara 的清單 | Rui 的清單 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
不過情況有點雜亂:Azara 的座標格式和排序方式似乎和 Rui 的不一樣,他們得不斷在兩份清單之間來回查看,才能弄清楚哪些寶物對應哪些地點。 身為剛開始學 Julia 的程式設計者,他們來找你幫忙寫個小程式(其實是一組函式),好把尋寶資訊整理得更有條理。
實作get_cooordinate()函式,它會接收 Azara 清單中的一組(treasure, coordinate)配對,並只回傳擷取出的地圖座標。
julia> get_cooordinate( ("Scrimshaw Whale's Tooth", "2A") )
"2A"
實作convert_coordinate()函式,它會接收格式為 "2A" 的座標,並回傳格式為('2', 'A')的元組。
julia> convert_coordinate("2A")
('2', 'A')
實作compare_records()函式,它會接收一組(treasure, coordinate)配對和一筆(location, coordinate, quadrant)記錄,並比較兩者的座標。
如果座標「相符」就回傳**true,不相符就回傳false**。
為了精確比較,請視需要重新格式化座標。
julia> compare_records(("Brass Spyglass", "4B"), ("Seaside Cottages", ('1', 'C'), "blue"))
false
julia> compare_records(("Model Ship in Large Bottle", "8A"), ("Harbor Managers Office", ('8', 'A'), "purple"))
true
實作create_record()函式,它會接收 Azara 清單中的一組(treasure, coordinate)配對和 Rui 清單中的一筆(location, coordinate, quadrant)記錄,並在座標相符時回傳(coordinate, location, quadrant, treasure)。
如果座標_不_相符,就回傳空的元組。 為了精確比較,請視需要重新格式化座標。
julia> create_record(("Brass Spyglass", "4B"), ("Abandoned Lighthouse", ('4', 'B'), "Blue"))
("4B", "Abandoned Lighthouse", "Blue", "Brass Spyglass")
julia> create_record(("Brass Spyglass", "4B"), ("Seaside Cottages", ('1', 'C'), "Blue"))
()