學習軌道
/
Julia
Julia
/
練習
/
Tisbury 尋寶之旅
Tisbury 尋寶之旅

Tisbury 尋寶之旅

學習練習

簡介

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 的清單
寶物 座標
Amethyst Octopus 1F
Angry Monkey Figurine 5B
Antique Glass Fishnet Float 3D
Brass Spyglass 4B
Carved Wooden Elephant 8C
Crystal Crab 6A
Glass Starfish 6D
Model Ship in Large Bottle 8A
Pirate Flag 7F
Robot Parrot 1C
Scrimshaw Whale's Tooth 2A
Silver Seahorse 4E
Vintage Pirate Hat 7E
地點名稱 座標 象限
Seaside Cottages ('1', 'C') Blue
Aqua Lagoon (Island of Mystery) ('1', 'F') Yellow
Deserted Docks ('2', 'A') Blue
Spiky Rocks ('3', 'D') Yellow
Abandoned Lighthouse ('4', 'B') Blue
Hidden Spring (Island of Mystery) ('4', 'E') Yellow
Stormy Breakwater ('5', 'B') Purple
Old Schooner ('6', 'A') Purple
Tangled Seaweed Patch ('6', 'D') Orange
Quiet Inlet (Island of Mystery) ('7', 'E') Orange
Windswept Hilltop (Island of Mystery) ('7', 'F') Orange
Harbor Managers Office ('8', 'A') Purple
Foggy Seacave ('8', 'C') Purple

不過情況有點雜亂:Azara 的座標格式和排序方式似乎和 Rui 的不一樣,他們得不斷在兩份清單之間來回查看,才能弄清楚哪些寶物對應哪些地點。 身為剛開始學 Julia 的程式設計者,他們來找你幫忙寫個小程式(其實是一組函式),好把尋寶資訊整理得更有條理。

1. 擷取座標

實作get_cooordinate()函式,它會接收 Azara 清單中的一組(treasure, coordinate)配對,並只回傳擷取出的地圖座標。

julia> get_cooordinate( ("Scrimshaw Whale's Tooth", "2A") )
"2A"

2. 格式化座標

實作convert_coordinate()函式,它會接收格式為 "2A" 的座標,並回傳格式為('2', 'A')的元組。

julia> convert_coordinate("2A")
('2', 'A')

3. 比對座標

實作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

4. 合併相符的記錄

實作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"))
()
透過 GitHub 編輯 連結會在新視窗或分頁中開啟
Julia Exercism

準備好開始 Tisbury 尋寶之旅 了嗎?

註冊 Exercism,透過 35 個概念128 個練習 和真人引導來學習並精通 Julia,全部免費。