跳至內容

Introducing Julia/Arrays and tuples

維基教科書,自由的教學讀本


« Introducing Julia
數組和元組
»
REPL 環境 類型

Storage: 數組 和 元組

[編輯]

在 Julia 中,相關項的組(related groups)通常存儲在數組(Arrays)、元組(Tuples)或字典(Dictionaries)中。

數組可用於存儲向量和矩陣。本節集中討論數組和元組;有關字典的更多信息參見 Dictionaries and Sets

數組

[編輯]

數組是元素的有序集合。它通常用方括號和逗號分隔的項表示。可以創建已滿或為空的數組,以及保存不同類型的值或僅限於特定類型的值的數組。

在 Julia 中,數組被用作列表(lists)、向量(vectors)、表(tables)和矩陣(matrices)。

一維數組充當向量或列表;二維數組可以用作表或矩陣;三維數組和多維數組同樣被看作是多維矩陣。

創建數組

[編輯]

創建簡單數組

[編輯]

下面的代碼演示如何創建一個簡單的一維數組:

julia> a = [1, 2, 3, 4, 5]
5-element Array{Int64,1}:
1
2
3
4
5

Julia 通知您 ("5-element Array{Int64,1}") 表示您創建了一個有 5 個元素(每個元素都是 64 位整數)的一維數組。並將變量 a 綁定到該數組。 請注意,這個過程很智能:例如,如果其中一個元素看起來像一個浮點數,您將得到 Float64 的數組:

julia> a1 = [1, 2, 3.0, 4, 5]
5-element Array{Float64,1}:
1.0
2.0
3.0
4.0
5.0

類似的對於各種字符串:

julia> s = ["this", "is", "an", "array", "of", "strings"]
6-element Array{String,1}:
"this"
"is"
"an"
"array"
"of"
"strings"

返回一個字符串的數組。

以及:

julia> trigfuns = [sin, cos, tan]
3-element Array{Function,1}:
sin
cos
tan

返回一個包含 Julia 函數的數組。

有許多不同的方法來創建數組:

您可以使它們成為空的、未初始化的、滿的、基於序列的、稀疏的、密集的等等。這取決於手頭的任務。

未初始化的

[編輯]

可以使用 Array{type}(dims) 指定數組的類型和維數 (注意是大寫的 "A"), 將該類型放入大括號中,並將長度放在括號中。 undef 表示數組尚未初始化為已知的值。

julia> array = Array{Int64}(undef, 5)
 5-element Array{Int64,1}:
 4520632328
 4614616448
 4520668544
 4520632328
 4615451376
 4294967362
julia> array3 = Array{Int64}(undef, 2, 2, 2)
2×2×2 Array{Int64,3}:
[:, :, 1] =
 4452254272  4452255728
 4452256400  4456808080

[:, :, 2] =
 4456808816  4452255728
 4456808816  4452254272

隨機的數字提醒您已經創建了一個未初始化的數組,但還沒有用任何合理的信息填充它。

包含任意類型元素的數組

[編輯]

可以使用不同類型的元素創建數組:

julia> [1, "2", 3.0, sin, pi]
5-element Array{Any, 1}:
 1
  "2"
 3.0
  sin
π = 3.1415926535897...

在這裏,數組有五個元素,但它們是一個奇怪的混合:數字、字符串、函數、常量。因此 Julia 創建了一個類型為 Any 的數組:

julia> typeof(ans)
Array{Any,1}

空數組

[編輯]

要創建特定類型的數組,還可以使用類型定義和方括號:

julia> Int64[1, 2, 3, 4]
4-element Array{Int64,1}:
1
2
3
4

如果您認為可以通過在聲明類型數組時偷偷輸入錯誤類型的值來愚弄 Julia,結果不會如您所願:

julia> Int64[1, 2, 3, 4, 5, 6, 7, 8,  9, 10.1]
ERROR: InexactError()

你也可以用這種方式創建空數組:

julia> b = Int64[]
0-element Array{Int64,1}
julia> b = String[]
0-element Array{String,1}
julia> b = Float64[]
0-element Array{Float64,1}

創建二維數組和矩陣

[編輯]

如果在定義陣列時省略逗號,則可以快速創建二維陣列。下面是一個單行、多列數組:

julia> [1 2 3 4]
1x4 Array{Int64,2}:
1  2  3  4

注意第一行輸出的 1x4 {...,2}

可以使用分號添加另一行:

julia> [1 2 3 4 ; 5 6 7 8]
2x4 Array{Int64,2}:
1  2  3  4
5  6  7  8

行向量和列向量

[編輯]

對比二者: [1,2,3,4,5][1 2 3 4 5].

使用逗號,此數組可以稱為「列向量」,由5行和1列組成:

julia> [1, 2, 3, 4, 5]
5-element Array{Int64,1}:
1
2
3
4
5

但使用空格時,此數組可以稱為「行向量」,由1行和5列組成:

julia> [1 2 3 4 5]
1x5 Array{Int64,2}:
1  2  3  4  5

注意 {Int64,2} 這裏告訴你 這是一個包含 Int64 (有 1 行和 5 列)的二維數組。在這兩種情況下,它們都是標準Julia數組。

這樣創建的數組可以用作矩陣:

julia> [1 2 3; 4 5 6]
2x3 Array{Int64,2}:
1  2  3
4  5  6

當然,您可以創建具有3個或更多維度的數組/矩陣。


有許多函數允許您一次性完成創建和填充數組。見 Creating and filling an array.

注意 Julia 是如何區分 Array{Float64,1}Array{Float64,2}:

julia> x = rand(5)
5-element Array{Float64,1}:
 0.4821773161183929 
 0.5811789456966778 
 0.7852806713801641 
 0.23626682918327369
 0.6777187748570226 
julia> x = rand(5, 1)
5×1 Array{Float64,2}:
 0.0723474801859294 
 0.6314375868614579 
 0.21065681560040828
 0.8300724654838343 
 0.42988769728089804

Julia 提供 Vector and Matrix 構造函數 。不過這些只是未初始化的一維數組和二維數組的別名:

julia> Vector(undef, 5)
5-element Array{Any,1}:
 #undef
 #undef
 #undef
 #undef
 #undef

julia> Matrix(undef, 5, 5)
5x5 Array{Any,2}:
 #undef  #undef  #undef  #undef  #undef
 #undef  #undef  #undef  #undef  #undef
 #undef  #undef  #undef  #undef  #undef
 #undef  #undef  #undef  #undef  #undef
 #undef  #undef  #undef  #undef  #undef

使用範圍對象 創建數組

[編輯]

在 Julia 中, 冒號 (:) 有很多種用法。一種用途是定義數字的範圍(Range) 和序列。可以通過直接鍵入範圍對象來創建該對象:

julia> 1:10
1:10

這種形式下看起來可能不是很有用,但它為 Julia 中任何需要數字範圍或序列的工作提供了原材料。

你可以在循環表達式中這麼使用:

julia> for n in 1:10 print(n) end
12345678910

或者使用 collect() 來建立一個由這些數字構成的數組:

julia> collect(1:10)
10-element Array{Int64,1}:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10

你也不必起始或結束使用整數:

julia> collect(3.5:9.5)
7-element Array{Float64,1}:
3.5
4.5
5.5
6.5
7.5
8.5
9.5

還有一個範圍對象的三塊版本 Start:Step:Stop,它允許您指定步長,而非默認的1。

例如,這將構建一個數組,該數組的元素從0到100,每10步執行一次:

julia> collect(0:10:100)
11-element Array{Int64,1}:
  0
 10
 20
 30
 40
 50
 60
 70
 80
 90
100

要降序而不是升序,您必須使用負的 step 值:

julia> collect(4:-1:1)
4-element Array{Int64,1}:
 4
 3
 2
 1

代替使用 collect() 來創建一個範圍的數組, 你可以在最後一個元素使用省略號運算符 (...)  :

julia> [1:6...]
6-element Array{Int64,1}:
 1
 2
 3
 4
 5
 6

(省略號運算符 ... 有時候被叫做 splat 運算符,它代表一系列參數)

然而, collect() 速度更快,並且是將範圍轉換為數組的推薦方法。

不過您可以在Julia中的許多情況下使用 Range 對象,並且不必總是將它們擴展為數組。

範圍 進一步使用

[編輯]

另一個有用的函數是 range(), 它構造一個從開始值到結束值的範圍對象,該對象採用一定大小的特定數量的 step。由於 Julia 通過組合關鍵字 step(), length() 以及 stop() 來為您計算缺少的部分,因此不必計算所有信息。

例如,要通過 12 步 從 1 到 100,請執行以下操作:

julia> range(1, length=12, stop=100)
1.0:9.0:100.0

或者從1開始走10步,在100點或之前停下來:

julia> range(1, stop=100, step=10)
1:10:91

如果您確實希望它以數組的形式出現,可以使用 Range 對象來構建一個數組:

julia> collect(range(1, length=12, stop=100))
12-element Array{Float64,1}:
  1.0
 10.0
 19.0
 28.0
 37.0
 46.0
 55.0
 64.0
 73.0
 82.0
 91.0
100.0

請注意,它提供了 Float64 數組,而不是 整型數組,即使這些值可能是整數。

對於對數範圍(有時稱為'log space'),你可以用簡單的 Range 對象並且用 exp10 函數廣播(broadcast)到該範圍的所有元素。

julia> exp10.(range(2.0, stop=3.0, length=5))
5-element Array{Float64,1}:
  100.0             
  177.82794100389228
  316.22776601683796
  562.341325190349  
 1000.0            

Broadcasting and dot syntax.

在 Range 對象中使用 step() 來指出 step 的大小:

julia> step(range(1, length=10, stop=100))
11.0

如果知道開始和步驟,但不知道結束,並且知道需要多少元素,請使用 range()

julia> range(1, step=3, length=20) |> collect
20-element Array{Int64,1}:
  1
  4
  7
 10
 13
 16
 19
 22
 25
 28
 31
 34
 37
 40
 43
 46
 49
 52
 55
 58

對 Range 中的值 collect

[編輯]

如您所見,如果未在 for 循環中使用 Range 對象,(如果需要)則可以使用 collect() 直接從Range對象獲取所有值:

julia> collect(0:5:100)
21-element Array{Int64,1}:
  0
  5
 10
 15
 20
 25
 30
 35
 40
 45
 50
 55
 60
 65
 70
 75
 80
 85
 90
 95
100

不過,在處理範圍之前,不必總是將範圍轉換為數組,因為通常可以直接迭代。例如,您不必這樣寫:

for i in collect(1:6)
    println(i)
end
 1
 2
 3
 4
 5
 6

因為如果你不用collect() 它也能很好地運行(而且可能更快):

for i in 1:6
    println(i)
end
 1
 2
 3
 4
 5
 6

使用推導和生成器創建數組

[編輯]

創建數組的一種有用方法是使用推導 (在 Comprehensions 中具體說明),其中每個元素都可以使用小型計算生成。

例如,要創建5個數字的數組,請執行以下操作:

julia> [n^2 for n in 1:5]
5-element Array{Int64,1}:
 1
 4
 9
16
25

使用兩個迭代器,可以輕鬆創建二維陣列或矩陣:

julia> [r * c for r in 1:5, c in 1:5]
5x5 Array{Int64,2}:
1   2   3   4   5
2   4   6   8  10
3   6   9  12  15
4   8  12  16  20
5  10  15  20  25

您可以在末尾添加 if 測試以篩選(或保留)通過測試的值:

julia> [i^2 for i=1:10  if i != 5]
9-element Array{Int64,1}:
   1
   4
   9
  16
  36
  49
  64
  81
 100

生成器的表達式類似,並且可以類似的方式使用:

julia> collect(x^2 for x in 1:10)
10-element Array{Int64,1}:
   1
   4
   9
  16
  25
  36
  49
  64
  81
 100
julia> collect(x^2 for x in 1:10 if x != 1)
9-element Array{Int64,1}:
   4
   9
  16
  25
  36
  49
  64
  81
 100

生成器表達式的優點是,它們在需要時生成值,而不是先構建一個數組來保存它們。

創建和填滿一個數組

[編輯]

有許多函數允許您創建具有特定內容的數組。當使用二維數組作為矩陣時,這些方法非常有用:

- zeros(m, n) 創建具有m行和n列的零數組/矩陣:

julia> zeros(2, 3)
2x3 Array{Float64,2}:
0.0  0.0  0.0
0.0  0.0  0.0

如有需要可以指定零的類型:

julia> zeros(Int64, 3, 5)
3×5 Array{Int64,2}:
 0  0  0  0  0
 0  0  0  0  0
 0  0  0  0  0

- ones(m, n) 創建一個全為1的 m 行 n列的數組或矩陣

julia> ones(2, 3)
2x3 Array{Float64,2}:
 1.0  1.0  1.0
 1.0  1.0  1.0

- rand(m, n) 創建全是隨機數的 m 行 n 列的矩陣:

julia> rand(2, 3)
2×3 Array{Float64,2}:
 0.488552   0.657078   0.895564
 0.0190633  0.0120305  0.772106

- rand(range, m, n) 創建給定範圍的隨機數矩陣:

julia> rand(1:6, 3, 3)
3x3 Array{Int64,2}:
 4  4  1
 3  2  3
 6  3  3

- randn(m, n) 創建 m 行 n 列矩陣。矩陣中充滿均值為0,標準差為1的常態分佈隨機數。


除了 zeros(), ones() 等函數之外,還有 trues(), falses(), fill(), 以及 fill!() 函數。

trues()falses() 函數用布爾值 true 或 false 填充數組:

julia> trues(3, 4)
3x4 BitArray{2}:
true  true  true  true
true  true  true  true
true  true  true  true

注意這個結果是 BitArray。

你可以使用 fill() 來創建具有特定值 (即重複數組)的數組,請執行以下操作:

julia> fill(42, 9)
9-element Array{Int64,1}:
42
42
42
42
42
42
42
42
42

julia> fill("hi", 2, 2)
2x2 Array{String,2}:
"hi"  "hi"
"hi"  "hi"

fill!() 有一個感嘆號標記 (! , 或者叫"bang") 警告您即將更改現有數組的內容。(這在 Julia 中是一種有效的指示)。

julia> a = zeros(10)
10-element Array{Float64,1}:
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0

julia> fill!(a, 42)
10-element Array{Float64,1}:
 42.0
 42.0
 42.0
 42.0
 42.0
 42.0
 42.0
 42.0
 42.0
 42.0 

讓我們「將一系列謬誤更改為真」:

julia> trueArray = falses(3,3)
3x3 BitArray{2}:
false  false  false
false  false  false
false  false  false
julia> fill!(trueArray, true)
3x3 BitArray{2}:
true  true  true
true  true  true
true  true  true
julia> trueArray
3x3 BitArray{2}:
true  true  true
true  true  true
true  true  true

你可以使用 range() 函數來創建類似向量的數組,接下來用 reshape() 把它們變為二維數組:

julia> a = reshape(range(0, stop=100, length=30), 10, 3)
10×3 reshape(::StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}, 10, 3) with eltype Float64:
  0.0      34.4828   68.9655
  3.44828  37.931    72.4138
  6.89655  41.3793   75.8621
 10.3448   44.8276   79.3103
 13.7931   48.2759   82.7586
 17.2414   51.7241   86.2069
 20.6897   55.1724   89.6552
 24.1379   58.6207   93.1034
 27.5862   62.069    96.5517
 31.0345   65.5172  100.0   

結果是一個10乘3的陣列,包含0和100之間的等間距數字。


重複元素以填充數組

[編輯]

repeat() 是通過重複較小的數組來創建數組的函數。


其語法的第一個選項是 repeat(A, n, m) ,源數組在第一維(行)中重複n次,在第二維(列)中重複m次。

您不必提供第二個維度,只需提供所需的行數:

julia> repeat([1, 2, 3], 2)
6-element Array{Int64,1}:
 1
 2
 3
 1
 2
 3

julia> repeat([1 2 3], 2)
2x3 Array{Int64,2}:
 1  2  3
 1  2  3

第二個選項表示額外的列:

julia> repeat([1, 2, 3], 2, 3)
6x3 Array{Int64,2}:
 1  1  1
 2  2  2
 3  3  3
 1  1  1
 2  2  2
 3  3  3

julia> repeat([1 2 3], 2, 3)
2x9 Array{Int64,2}:
 1  2  3  1  2  3  1  2  3
 1  2  3  1  2  3  1  2  3

repeat() 函數還允許您通過複製源數組的行和列來創建數組。「內部」和「外部」選項確定是否重複行和/或列。例如,INNER=[2,3]生成一個數組,其中每行有兩個副本,每列有三個副本:

innerouter 選項 決定是否重複行 和/或 列。例如, inner = [2, 3] 生成一個數組,其中行拷貝兩份,列拷貝三分:

julia> repeat([1, 2], inner = [2, 3])
4x3 Array{Int64,2}:
 1  1  1
 1  1  1
 2  2  2
 2  2  2 

相比之下, 這裏 outer = [2,3]:

julia> repeat([1, 2], outer = [2, 3])
4x3 Array{Int64,2}:
 1  1  1
 2  2  2
 1  1  1
 2  2  2

注意後者等同於 repeat([1, 2], 2, 3)outer 關鍵字的一個更有意義的示例是當它與 inner 關鍵字組合時。

此時,初始矩陣的每一行的每個元素都是行重複的,然後,生成的矩陣的每一行切片都是三列重複的:

 julia> repeat([1 2; 3 4], inner=(2, 1), outer=(1, 3))
 4×6 Array{Int64,2}:
  1  2  1  2  1  2
  1  2  1  2  1  2
  3  4  3  4  3  4
  3  4  3  4  3  4

Array 構造器

[編輯]

我們在前面看到過為您構建特定類型的數組:Array() :

julia> Array{Int64}(undef, 6)
6-element Array{Int64,1}:
 4454517776
 4454517808
 4454517840
 4454517872
 4454943824
 4455998977

這是未初始化的;看起來奇怪的數字只是分配給新數組之前內存的舊內容。

嵌套數組

[編輯]

創建嵌套數組很簡單。有時我們要指定一下初始內容:

   julia> a = Array[[1, 2], [3,4]]
   2-element Array{Array,1}:
    [1, 2]
    [3, 4]

Array 構造器 也可以構建 數組的數組:

julia> Array[1:3, 4:6]
 2-element Array{Array,1}:
 [1,2,3]
 [4,5,6]

您當然可以通過 reshape() 函數隻創建一個簡單的數組,然後更改其形狀:

julia> reshape([1, 2, 3, 4, 5, 6, 7, 8], 2, 4)
2x4 Array{Int64,2}:
1  3  5  7
2  4  6  8

同樣的技術也可用於創建三維陣列。下面是一個三維字符串數組:

julia> Array{String}(undef, 2, 3, 4)
2x3x4 Array{String,3}:
[:, :, 1] =
#undef  #undef  #undef
#undef  #undef  #undef
[:, :, 2] =
#undef  #undef  #undef
#undef  #undef  #undef
[:, :, 3] =
#undef  #undef  #undef
#undef  #undef  #undef
[:, :, 4] =
#undef  #undef  #undef
#undef  #undef  #undef

每個元素都被設置為 '未定義' — #undef.

push!() 函數將另一項推送到數組的最後:

julia> push!(a, rand(1:100, 5))
3-element Array{Array,1}:
[1, 2]
[3, 4]
[4, 71, 82, 60, 48]

julia> push!(a, rand(1:100, 5))
4-element Array{Array,1}:
[1,2]
[3,4]
[4, 71, 82, 60, 48]
[4, 22, 52, 5, 14]

或者你想創建一個空的數組:

julia> a = Array{Int}[]
0-element Array{Array{Int64,N} where N,1}

julia> push!(a, [1, 2, 3])
1-element Array{Array{Int64,N} where N,1}:
[1, 2, 3]

julia> push!(a, [4, 5, 6])
2-element Array{Array{Int64,N} where N,1}:
[1, 2, 3]
[4, 5, 6]

你可以用 Vector 作為 Array 的別名:

julia> a = Vector{Int}[[1, 2], [3, 4]]
2-element Array{Array{Int64,1},1}:
[1, 2]
[3, 4]

julia> push!(a,  rand(1:100, 5))
3-element Array{Array{Int64, 1},1}:
[1, 2]
[3, 4]
[12, 65, 53, 1, 82]
    
julia> a[2]
2-element Array{Int64,1}:
3
4
    
julia> a[2][1]
3

複製數組

[編輯]

如果您有一個現有的數組,並且希望創建另一個具有相同維數的數組,則可以使用 similar() 函數:

julia> a = collect(1:10); # hide the output with the semicolon
julia> b = similar(a)
10-element Array{Int64,1}:
 4482975872
 4482975792
          1
 4482975952
 4482976032
 4482976112
          3
          3
          2
 4520636161

請注意,數組維度是被複製了,但是值沒有被複製,它們是從隨機的內存中複製的。

不過,您仍然可以更改類型和尺寸,因此它們不必如此相似:

julia> c = similar(b, String, (2, 2))
2x2 Array{String,2}:
#undef  #undef
#undef  #undef

在任何情況下都有一個 copy() 函數。

矩陣操作:把數組作為矩陣來用

[編輯]

在Julia中,二維數組可以用作矩陣。(如果維數和內容允許的話)所有可用於處理數組的函數都可以用作矩陣。

鍵入矩陣的一種快速方法是使用空格(生成行)分隔元素,並使用分號分隔行。所以:

θ

你也可以這樣做:

julia> id  = reshape([1, 2, 3, 4], 2, 2)
2×2 Array{Int64,2}:
 1  3
 2  4

它接受一個標準數組並對其調整形狀,使其在兩行和兩列中運行。請注意,矩陣是逐列填充的。

如果你不使用逗號或分號:

 julia> [1 2 3 4]

你將創建一個單行的數組/矩陣

1x4 Array{Int64,2}:
1  2  3  4

在每種情況下,請注意在類型值後面的大括號 ({Int64,2}) 中的2。這表示二維數組。

可以通過相鄰粘貼兩個數組來創建數組,如下所示:

julia> [[1, 2, 3], [4, 5, 6]]
 2-element Array{Array{Int64,1},1}:
 [1, 2, 3]
 [4, 5, 6]

當您省略逗號時,您將在每個列旁邊放置列,您將得到以下結果:

julia> [[1, 2, 3] [4, 5, 6]]
3×2 Array{Int64,2}:
 1  4
 2  5
 3  6

訪問數組的內容

[編輯]

若要訪問數組或矩陣的元素,請在數組名稱後加上方括號中的元素編號。以下是一維數組:

julia> a = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]

這是第五個元素:

julia> a[5]
50

第一個元素索引號為1。Julia是從 1 而不是 0 開始對列表和數組中的元素進行索引的語言之一。

(因此,它屬於 Matlab、Mathematica、Fortran、Lua 和 Smalltalk 等精英公司,而其他大多數程式語言則堅定地站在基於 0 的索引器的對立面。【譯者註:應該是基於1的索引器的對立面?下為原文:】)

(And thus it's in the elite company of Matlab, Mathematica, Fortran, Lua, and Smalltalk, while most of the other programming languages are firmly in the opposite camp of 0-based indexers.)

最後一個元素稱為 end (而不是像在其他一些語言中的-1):

julia> a[end]
100

類似地,您可以通過以下方式訪問倒數第二個元素

julia> a[end-1]
90

(倒數第三個元素類似,依此類推)。

您可以提供一組索引號,這些索引號分別放在兩端的一對括號中:

julia> a[[3,6,2]]
3-element Array{Int64,1}:
 30
 60
 20

或提供一個範圍的索引編號:

julia> a[2:2:end]
5-element Array{Int64,1}:
  20
  40
  60
  80
 100

You can even select elements using true and false values:

甚至可以使用truefalse 值來選擇元素:

julia> a[[true, true, false, true, true, true, false, true, false, false]]
6-element Array{Int64,1}:
 10
 20
 40
 50
 60
 80

下面是一個2D數組,其中的行由分號分隔:

julia> a2 = [1 2 3; 4 5 6; 7 8 9]
3x3 Array{Int64,2}:
1  2  3
4  5  6
7  8  9

julia> a2[1]
1

如果您只要求2D數組的一個元素,您將得到一個值,就好像該數組是一列地展開的,即先向下,然後交叉。在這種情況下,您將得到4,而不是2:

julia> a2[2]
4

如您所想的請求行,然後列:

julia> a2[1, 2]
2

即行1,列2。下面是第 1 行第 3 列:

julia> a2[1, 3]
3

但是不要以錯誤的方式獲取行/列索引:

julia> a2[1, 4]
ERROR: BoundsError: attempt to access 3×3 Array{Int64,2} at index [1, 4]
Stacktrace:
 [1] getindex(::Array{Int64,2}, ::Int64, ::Int64) at ./array.jl:498

順便說一下,有一種從數組獲取元素的替代方法:getindex() 函數:

julia> getindex(a2, 1, 3)
3
 
julia> getindex(a2, 1, 4)
ERROR: BoundsError: attempt to access 3×3 Array{Int64,2} at index [1, 4]
Stacktrace:
 [1] getindex(::Array{Int64,2}, ::Int64, ::Int64) at ./array.jl:498

使用冒號表示行或列。例如,下面是「每行第二列」:

julia> a2[:, 2]
3-element Array{Int64,1}:
2
5
8

下面是「第二行,每列」:

julia> a2[2, :]
3-element Array{Int64,1}:
 4
 5
 6

元素級操作和向量化操作

[編輯]

許多Julia函數和運算符專為處理數組而設計。這意味着您不必總是對一個數組單獨處理每個元素。

一個簡單的例子是使用基本的算術運算符。如果其他參數為單一值,則可以直接在數組中使用這些參數:

julia> a = collect(1:10);
julia> a * 2
10-element Array{Int64,1}:
  2
  4
  6
  8
 10
 12
 14
 16
 18
 20

新數組的每個元素都是原來的乘以2。同樣:

julia> a / 100
10-element Array{Float64,1}:
0.01
0.02
0.03
0.04
0.05
0.06
0.07
0.08
0.09
0.1

新數組的每個元素都是原來的除以100。


這些操作被描述為元素操作


可以在許多運算符的前面加上一個點(.). 這些與它們的無點版本相同,按元素處理數組元素。

例如,可以使用 .* 來使用乘法函數(*)。這使您可以將數組或範圍按元素相乘:

julia> n1 = 1:6;
julia> n2 = 100:100:600;
julia> n1 .* n2
6-element Array{Int64,1}:
 100
 400
 900
1600
2500
3600

結果的第一個元素是通過將兩個數組的第一個元素相乘得到的結果,以此類推。


除了算術運算符,一些比較運算符也有元素操作的版本。

例如,在循環中使用 .== 來比較兩個數組,而不是使用 ==

下面是兩個由 10 個數字組成的數組,一個是連續的,另一個是無序的,並且進行了元素比較,以查看數組 b 中有多少個元素與數組 a 恰好位於同一位置:

julia> a = 1:10; b=rand(1:10, 10); a .== b
10-element BitArray{1}:
 true
false
 true
false
false
false
false
false
false
false

Broadcasting: dot syntax for vectorizing functions

[編輯]

這種使用的語法將函數元素應用於數組的技術稱為 廣播

在函數名後面,開括號前面加一個點,並提供一個數組或範圍作為參數。

例如,下面是一個簡單的函數,它將兩個數字相乘:

julia> f(a, b) = a * b
f (generic function with 1 method)

它在兩個純量上按預期工作:

julia> f(2, 3)
6 

但是,將此函數應用於數組是很容易的。只需使用點語法:

julia> f.([1, 4, 2, 8, 7], 10)
5-element Array{Int64,1}:
 10
 40
 20
 80
 70
julia> f.(100, 1:10)
10-element Array{Int64,1}:
  100
  200
  300
  400
  500
  600
  700
  800
  900
 1000

在第一個示例中,Julia 自動將第二個參數視為數組,保證乘法操作正確。

min() 和 max()

[編輯]

注意 max()min(). 你可能會覺得 max() 可以在數組上使用,就像這樣,查找一個最大的元素:

julia> r = rand(0:10, 10)
10-element Array{Int64,1}:
 3
 8
 4
 3
 2
 5
 7
 3
10
10 

但是,不行……

julia> max(r)
LoadError: MethodError: no method matching max(::Array{Int64,1})
...

max 函數返回其參數中最大的一個。要查找數組中最大的元素,可以使用相關函數maximum()

julia> maximum(r)
10

可以對兩個或更多個數組使用 max() 執行元素檢查,返回另一個包含最大值的數組:

julia> r = rand(0:10, 10); s = rand(0:10, 10); t = rand(0:10,10);
julia> max(r, s, t)
10-element Array{Int64,1}:
 8
 9
 7
 5
 8
 9
 6
10
 9
 9

min()minimum() 的行為方式類似。

使最大值適用於數組的一種方法是使用省略號(splat)運算符:

julia> max(r...)
9

可以使用按元素排列的運算符測試數組的每個值,並在單個操作中對其進行更改。下面是一個從0到10的隨機整數組:

julia> a = rand(0:10,10, 10)
10x10 Array{Int64,2}:
10   5   3   4  7   9  5   8  10   2
 6  10   3   4  6   1  2   2   5  10
 7   0   3   4  1  10  7   7   0   2
 4   9   5   2  4   2  1   6   1   9
 0   0   6   4  1   4  8  10   1   4
10   4   0   5  1   0  4   4   9   2
 9   4  10   9  6   9  4   5   1   1
 1   9  10  10  1   9  3   2   3  10
 4   6   3   2  7   7  5   4   6   8
 3   8   0   7  1   0  1   9   7   5

現在可以測試每個值是否等於0,然後僅將這些元素設置為 11,如下所示:

julia> a[a .== 0] .= 11;
julia> a
10x10 Array{Int64,2}:
10   5   3   4  7   9  5   8  10   2
 6  10   3   4  6   1  2   2   5  10
 7  11   3   4  1  10  7   7  11   2
 4   9   5   2  4   2  1   6   1   9
11  11   6   4  1   4  8  10   1   4
10   4  11   5  1  11  4   4   9   2
 9   4  10   9  6   9  4   5   1   1
 1   9  10  10  1   9  3   2   3  10
 4   6   3   2  7   7  5   4   6   8
 3   8  11   7  1  11  1   9   7   5

這是因為 a .== 0 返回一個包含 truefalse 值的數組,然後使用這些值選擇要設置為 11 的 a 的元素。

如果您正在對二維矩陣進行計算,您可能需要閱讀更多關於矩陣算術的內容: Matrix arithmetic

行與列

[編輯]

對於二維數組,可以使用括號、冒號和逗號提取單個行和列或行和列的範圍。

對此 table :

julia> table = [r * c for r in 1:5, c in 1:5]
5x5 Array{Int64,2}:
1   2   3   4   5
2   4   6   8  10
3   6   9  12  15
4   8  12  16  20
5  10  15  20  25

您可以使用以下命令找到一行(請注意逗號):

julia> table[1, :]
1x5 Array{Int64,2}:
5-element Array{Int64,1}:
 1
 2
 3
 4
 5

您可以得到一個範圍內的行,其後跟一個逗號和一個冒號:

julia> table[2:3,:]
2x5 Array{Int64,2}:
2  4  6   8  10
3  6  9  12  15

要選擇列,請以冒號開頭,後跟逗號:

julia> table[:, 2]
5-element Array{Int64,1}:
 2
 4
 6
 8
10

冒號本身訪問整個數組:

julia> table[:]
25-element Array{Int64,1}:
 1
 2
 3
 4
 5
 2
 4
 6
 8
10
 3
 6
 9
12
15
 4
 8
12
16
20
 5
10
15
20
25 

要提取列範圍,請執行以下操作:

julia> table[:, 2:3]
5x2 Array{Int64,2}:
 2   3
 4   6
 6   9
 8  12
10  15

數組中查找元素

[編輯]

如果您想知道數組是否包含項,請使用 in() 函數,可以通過兩種方式調用該函數:

julia> a = 1:10
julia> 3 in a
true

或者作為函數調用:

julia> in(3, a) # needle ... haystack
true

有一組以 find 開頭的函數,例如 findall(), findfirst(), findnext(), findprev()findlast(),您可以使用這些函數來獲取匹配特定值的數組單元格的索引,或者傳入一個判斷。其中每一種都有兩種或兩種以上的形式。


下面是一組小質數:

julia> smallprimes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29];

要查找數字的第一個匹配項並獲取其索引,可以使用 findfirst() 函數的以下方法:

julia> findfirst(isequal(13), smallprimes)
6

因此,數組中的第一個 13 出現在第六個單元格中:

julia> smallprimes[6]
13

該函數類似於Julia中的許多函數,接受一個函數作為第一個參數。該函數應用於數組的每個元素,如果函數返回true,則返回該元素或其索引。

該函數返回第一個元素的索引。


下面是另一個使用匿名函數的示例:

julia> findfirst(x -> x == 13, smallprimes)
6

findall() 函數返回索引數組,指向應用時函數返回true的每個元素:

julia> findall(isinteger, smallprimes)
10-element Array{Int64,1}:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
julia> findall(iseven, smallprimes)
1-element Array{Int64,1}:
1

請記住,這些是索引號的數組,而不是實際的單元格值。索引可用於使用標準的方括號語法提取相應的值:

julia> smallprimes[findall(isodd, smallprimes)]
9-element Array{Int64,1}:
 3
 5
 7
11
13
17
19
23
29

鑑於 findfirst() 返回一個數字,即第一個匹配單元格的索引:

julia> findfirst(iseven, smallprimes)
1
julia> smallprimes[findfirst(iseven, smallprimes)]
2

findnext() 函數與 findall()findfirst() 函數非常相似,但它接受一個額外的數字,告訴函數從數組中間的某個位置開始搜索,而不是從頭開始。


例如,如果 findfirst(smallprimes,13) 查找數組中數字 13 第一次出現的索引,則可以在findnext() 中使用以下值從此處繼續搜索:

julia> findnext(isodd, smallprimes, 1 + findfirst(isequal(13), smallprimes))
7
julia> smallprimes[ans]
17

findin(A, B) 函數返回數組 A 中的元素可在數組 B 中找到的元素的索引:

julia> findall(in([11, 5]), smallprimes)
2-element Array{Int64,1}:
3
5

julia> smallprimes[3]
5

julia> smallprimes[5]
11

應該注意索引的返回順序。

Finding out about an array

[編輯]

對於二維數組:

julia> a2 = [1 2 3; 4 5 6; 7 8 9]
3x3 Array{Int64,2}:
1  2  3
4  5  6
7  8  9

我們可以使用以下函數了解有關它的更多信息:

  • ndims()
  • size()
  • length()
  • count()

ndims() 返回維數。向量為1,表為2,依此類推:

julia> ndims(a2)
2

size() 以元組的形式返回數組的行數和列數:

julia> size(a2)
(3,3)

length() 告訴您數組包含多少元素:

julia> length(a2)
9

你可以使用 count() 來查找特定值出現的次數。例如,有多少個非零項?

julia> count(!iszero, a2)
9

要查找數組/矩陣的逆、行列式和其他方面,請參見 Manipulating matrices.。

要在索引號 (從 1 到 n) 和 行/列號 (1:r, 1:c) 之間進行轉換, 可以使用:

julia> CartesianIndices(a2)[6]
CartesianIndex(3, 2)

例如,查找第六個元素的行和列。

在另一個方向上,什麼索引號對應於第3行,第2列?

使用與笛卡爾索引相反的線性索引:

julia> LinearIndices(a2)[3, 2]
6

數組比較

[編輯]

union() 構建一個新數組,該數組是兩個或多個數組的聯合或組合。該操作將刪除重複項,並且結果包含每個元素的唯一版本:

julia> odds = collect(1:2:10)
5-element Array{Int64,1}:
1
3
5
7
9
julia> evens = collect(2:2:10)
5-element Array{Int64,1}:
 2
 4
 6
 8
10
julia> union(odds, evens)
10-element Array{Int64,1}:
 1
 3
 5
 7
 9
 2
 4
 6
 8
10

請注意,新聯合的順序反映了原始順序。此示例根本不對數字進行排序:

julia> union(1:5, 1:10, 5:-1:-5)
16-element Array{Int64,1}:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
 0
-1
-2
-3
-4
-5

intersect() 返回一個新數組,該數組是兩個或多個數組的交集。結果包含每個元素的一個匹配項,但僅當它出現在每個數組中時:

julia> intersect(1:10, 5:15)
5:10
julia> intersect(5:20, 1:15, 3:12)
5:12

setdiff() 查找兩個數組之間的不同,即 是第一個數組中的元素,而不是第二個數組中的元素:

julia> setdiff(1:15, 5:20)
4-element Array{Int64,1}:
1
2
3
4
julia> setdiff(5:20, 1:15)
5-element Array{Int64,1}:
16
17
18
19
20

過濾 filter

[編輯]

有一組相關函數可以讓您處理數組的元素。

filter() 在元素通過測試時查找並保留這些元素。在這裏,我們使用 isodd() 函數 (將其作為不帶括號的命名函數傳遞,而不是帶括號的函數調用) 來過濾(保留)所有 數組中是奇數的項。

julia> filter(isodd, 1:10)
5-element Array{Int64,1}:
 1
 3
 5
 7
 9

和許多 Julia 函數一樣,有一個版本可以更改數組。因此 filter() 返回原始數據的副本,但 filter!() 改變了數組。

我們前面遇到的 count() 函數類似於 filter(), 但只計算滿足條件的元質數:

julia> count(isodd, 1:100)
50

另外,any() 函數隻告訴您任何元素是否滿足條件:

julia> any(isodd, 1:100)
true

all() 函數告訴您是否所有元素都滿足條件。在這裏 all() 檢查 filter() 是否正確地完成了這項工作。

julia> all(isodd, filter(isodd, 1:100))
true

隨機元素

[編輯]

要從陣列中選擇隨機元素,請執行以下操作:

julia> a = collect(1:100);
julia> a[rand(1:end)]
14

其他函數

[編輯]

數組是 Julia 的基礎,這裏無法具體描述幾十個數組處理函數。但這裏有幾個選擇:

找到數組中的極值:

julia> a = rand(100:110, 10)

10-element Array{Int64,1}:
 109
 102
 104
 108
 103
 110
 100
 108
 101
 101
julia> extrema(a)
(100,110)

findmax() 查找最大元素並在元組中返回它及其索引:

julia> findmax(a)
(110,6)

例如 sum(), prod(), mean(), middle(), 會執行你所期望的操作:


mean()middle() 已移到標準庫的 Statistics 模塊中,您可能需要首先輸入 "using Statistics" 才能使用它們)

julia> sum(a)
1046
julia> prod(1:10)
3628800
julia> mean(a)
104.6
julia> middle(a)
105.0

sum(), mean(), and prod() 還允許提供函數:將該函數應用於每個元素,然後對結果求和/平均值/積:

julia> sum(sqrt, 1:10)  # the sum of the square roots of the first 10 integers 前10个整数的平方根之和 
22.4682781862041

julia> mean(sqrt, 1:10) # the mean of the square roots of the first 10 integers 前十个证书的平方根的平均值
2.24682781862041

Combinatorics.jl 包中的函數允許您查找數組的組合和排列。 combinations() 查找數組中所有可能的元素組合:您可以指定每個組合中的元質數:

julia> Pkg.add("Combinatorics") # (do this just once)
julia> using Combinatorics
julia> collect(combinations(a, 3))
120-element Array{Array{Int64,1},1}:
 [109,102,104]
 [109,102,108]
 [109,102,103]
 [109,102,110]
 [109,102,100]
 [109,102,108]
 [109,102,101]
 [109,102,101]
 [109,104,108]
 [109,104,103]
 [109,104,110]
 [109,104,100]
 [109,104,108]
 ⋮            
 [103,108,101]
 [103,101,101]
 [110,100,108]
 [110,100,101]
 [110,100,101]
 [110,108,101]
 [110,108,101]
 [110,101,101]
 [100,108,101]
 [100,108,101]
 [100,101,101]
 [108,101,101]

以及 permutations() 生成所有的排列。實際上,您可能不需要使用 collect() 將項收集到數組中:

julia> length(permutations(a))
3628800

改變數組內容: 添加刪除元素

[編輯]

要在數組末尾添加項,請使用 push!():

julia> a = collect(1:10); push!(a, 20)
11-element Array{Int64,1}:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
20

與往常一樣,感嘆號會提醒您此函數會更改數組。你只能將其 push 到向量的末端。

要在前面添加元素,請使用 pushfirst!():

julia> pushfirst!(a, 0)
12-element Array{Int64,1}:
 0
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
20

若要在給定索引處將元素插入到數組中,請使用 splice!() 例如,下面是一個明顯有遺漏的數字列表:

julia> a = [1, 2, 3, 5, 6, 7, 8, 9]
8-element Array{Int64,1}:
1
2
3
5
6
7
8
9

使用 splice!() 在特定的索引值範圍內插入序列。Julia返回已替換的值。數組會增長以容納新的元素,並且在序列插入之後,元素會被向下推。讓我們在位置 4:5 的地方插入範圍 4:6

julia> splice!(a, 4:5, 4:6)
2-element Array{Int64,1}:
 5
 6

您可能會嘗試檢查是否正確插入了新值:

julia> a
9-element Array{Int64,1}:
 1
 2
 3
 4
 5
 6
 7
 8
 9

現在,如果要在特定的索引間位置插入一些值,則必須使用稱為「空範圍」的功能。在這種情況下,索引 n-1 和 n 之間的間隔表示為 n:n-1

例如:

julia> L = ['a','b','f']
3-element Array{Char,1}:
 'a'
 'b'
 'f'
julia> splice!(L, 3:2, ['c','d','e'])
0-element Array{Char,1}
julia> L
6-element Array{Char,1}:
 'a'
 'b'
 'c'
 'd'
 'e'
 'f'

刪除元素

[編輯]

如果不提供替換,也可以使用 splice!() 來刪除元素並移動其餘元素。

julia> a = collect(1:10); 
julia> splice!(a,5);
julia> a
9-element Array{Int64,1}:
 1
 2
 3
 4
 6
 7
 8
 9
10

要刪除最後一項,請執行以下操作:

julia> pop!(a)
10

刪除第一項:

julia> popfirst!(a)
1

More aggressive modification of arrays (and similar data structures) can be made with functions such as deleteat!() and splice!(). You can find out the indices of elements in various ways. Once you know the indices, you can use deleteat!() to delete an element, given its index number:

julia> a = collect(1:10);
julia> findfirst(isequal(6), a)
4
julia> deleteat!(a, findfirst(isequal(6), a))
9-element Array{Int64,1}:
 1
 2
 3
 4
 5
 7
 8
 9
10

deleteat!() also accepts a range or iterator to specify the indices, so you can do this:

julia> deleteat!(a, 2:6)
4-element Array{Int64,1}:
  1
  8
  9
 10

Remember that you can always remove a group of elements using a filter: see Filtering.

其他函數

[編輯]

If you want to do something to an array, there's probably a function to do it, and sometimes with an exclamation mark to remind you of the potential consequences. Here are a few more of these array-modifying functions:

  • resize!() change the length of a Vector
  • append!() push a second collection at the back of the first one
  • prepend!() insert elements at the beginning of the first Vector
  • empty!(a) remove all elements
  • rotr90(a) make a copy of an array rotated 90 degrees clockwise:
julia> rotr90([1 2 3 ; 4 5 6])
3x2 Array{Int64,2}:
4  1
5  2
6  3
  • circshift(a) move the elements around 'in a circle' by a number of steps:
julia> circshift(1:6, 1)
6-element Array{Int64,1}:
 6
 1
 2
 3
 4
 5

This function can also do circular shifts on 2D arrays too. For example, here's a table:

julia> table = collect(r*c for r in 1:5, c in 1:5)
5×5 Array{Int64,2}:
 1   2   3   4   5
 2   4   6   8  10
 3   6   9  12  15
 4   8  12  16  20
 5  10  15  20  25

By supplying a tuple you can move rows and columns. For example: moving the columns by 0 and the rows by 1 moves the first dimension by 0 and the second by 1. The first dimension is downwards, the second rightwards:

julia> circshift(table, (0, 1))
5×5 Array{Int64,2}:
  5  1   2   3   4
 10  2   4   6   8
 15  3   6   9  12
 20  4   8  12  16
 25  5  10  15  20

There's a modifying version of circshift(), circshift!

設置數組內容

[編輯]

To set the contents of an array, specify the indices on the left-hand side of an assignment expression:

julia> a = collect(1:10);

julia> a[9]= -9
-9

To check that the array has really changed:

julia> print(a)
[1,2,3,4,5,6,7,8,-9,10]

You can set a bunch of elements at the same time, using the broadcasting assignment operator:

julia> a[3:6] .= -5
4-element view(::Array{Int64,1}, 3:6) with eltype Int64:
 -5
 -5
 -5
 -5
julia> print(a)
[1,2,-5,-5,-5,-5,7,8,-9,10]

And you can set a sequence of elements to a suitable sequence of values:

julia> a[3:9] = collect(9:-1:3)
7-element Array{Int64,1}:
9
8
7
6
5
4
3

Notice here that, although Julia shows the 7 element slice as the return value, in fact the whole array has been modified:

julia> a
10-element Array{Int64,1}:
 1
 2
 9
 8
 7
 6
 5
 4
 3
10

You can set ranges to a single value in one operation using broadcasting:

julia> a[1:5] .= 0
0
julia> a
10-element Array{Int64,1}:
  0
  0
  0
  0
  0
  6
  7
  8
  9
 10
julia> a[1:10] .= -1;
-1
julia> print(a)
[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1]

As an alternative to the square bracket notation, there's a function call version that does the same job of setting array contents, setindex!():

julia> setindex!(a, 1:10, 10:-1:1)
10-element Array{Int64,1}:
10
 9
 8
 7
 6
 5
 4
 3
 2
 1

You can refer to the entire contents of an array using the colon separator without start and end index numbers, i.e. [:]. For example, after creating the array a:

julia> a = collect(1:10);

we can refer to the contents of this array a using a[:]:

julia> b = a[:]
10-element Array{Int64,1}:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10

julia> b[3:6]
4-element Array{Int64,1}:
3
4
5
6

把數組傳遞給函數

[編輯]

函數不能夠改變傳遞進來的參數的值,但是可以對傳遞進來的 容器 的內容進行修改。


請考慮以下函數,該函數將其參數更改為5:

julia> function set_to_5(x)
        x = 5
	end
set_to_5 (generic function with 1 method)
julia> x = 3
3
julia> set_to_5(x)
5
julia> x
3

儘管函數裏面的 x 被改變了 ,函數外面的 x 也沒有變。函數裏面的變量名是局部的。

但是,你可以改變一個容器的內容,比如數組。下面一個函數使用 語法來獲取 容器 x 的內容,而不是直接改變 變量x 的值。


julia> function fill_with_5(x)
         x[:] .= 5
       end
fill_with_5 (generic function with 1 method)
julia> x = collect(1:10)
10-element Array{Int64,1}:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
julia> fill_with_5(x)
5
julia> x
10-element Array{Int64,1}:
5
5
5
5
5
5
5
5
5
5

If, instead of accessing the container variable's contents, you try to change the variable itself, it won't work. For example, the following function definition creates an array of 5s in temp and then attempts to change the argument x to be temp.

julia> function fail_to_fill_with_5(x)
         temp = similar(x)
         for i in 1:length(x)
            temp[i] = 5
         end
         x = temp
       end
fail_to_fill_with_5 (generic function with 1 method)
julia> x = collect(1:10)
10-element Array{Int64,1}:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
julia> fail_to_fill_with_5(x)
10-element Array{Int64,1}:
5
5
5
5
5
5
5
5
5
5

It looks like it worked, but:

julia> x
10-element Array{Int64,1}:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10

You can change elements of the array, but you can't change the variable so that it points to a different array. In other words, your function isn't allowed to change the binding between the argument and the array that was passed to it.

Julia's way of handling function arguments is described as 「pass-by-sharing」. An array isn't copied when you pass it to a function (that would be very inefficient for large arrays).

矩陣運算

[編輯]

For matrix-on-matrix arithmetic action, you can:

- add (+) and subtract (-):

θ

θ

θ


θ


- multiply (*), assuming the dimensions are compatible, so m1 * m2 is possible if last(size(m1)) == first(size(m2)). Note the difference between matrix multiplication and elementwise matrix multiplication. Here's a matrix A:

θ

and here's matrix B:

θ

The .* broadcasting operator multiplies them elementwise:

θ

Compare this with matrix multiplication, A * B:

θ

which is:

julia> [1 * 10 + 2 * 12        1 * 11 + 2 * 13  ;      3 * 10 + 4 * 12     3 * 11 + 4 * 13]
 2x2 Array{Int64,2}:
  34  37
  78  85

- division of two matrices. You can use the backslash (\) for left division:

julia> A = rand(1:9, 3, 3)
 3x3 Array{Int64,2}:
  5  4  3
  8  7  7
  9  3  7
 julia> B = rand(1:9, 3, 3)
 3x3 Array{Int64,2}:
  6  5  5
  6  7  5
  7  2  7
 julia> A \ B
 3x3 Array{Float64,2}:
2.01961    0.411765   1.84314
0.254902   1.35294   -0.0392157
  -1.70588   -0.823529  -1.35294

and the forward slash (/) right or slash division:

julia> A / B
3x3 Array{Float64,2}:
4.0       -2.0       -1.0     
0.285714   0.714286   0.285714
5.07143   -3.07143   -0.428571

With a matrix and a scalar, you can add, subtract, multiply, and divide:

julia> A + 1
3x3 Array{Int64,2}:
  6  5  4
  9  8  8
 10  4  8
julia> [1 2 3 4 5] * 2
1x5 Array{Int64,2}:
 2  4  6  8  10
julia> A .- 1
3x3 Array{Int64,2}:
 4  3  2
 7  6  6
 8  2  6
julia> A .* 2
3x3 Array{Int64,2}:
 10   8   6
 16  14  14
 18   6  14
julia> A ./ 2
3x3 Array{Float64,2}:
 2.5  2.0  1.5
 4.0  3.5  3.5
 4.5  1.5  3.5

and more besides:

julia> A // 2
3x4 Array{Rational{Int64},2}:
 1//2  2//1  7//2   5//1
 1//1  5//2  4//1  11//2
 3//2  3//1  9//2   6//1
julia> A .< 6
3x3 BitArray{2}:
  true   true   true
 false  false  false
 false   true  false

You can multiply matrix and a vector (the matrix-vector product), if the arrays have compatible shapes. Here's the matrix A:

θ

and here's a vector V:

θ

The * operator multiplies them:

θ

The dot or inner product (aTb) can be found using the dot() function, but you'll have to import the LinearAlgebra library first:

julia> using LinearAlgebra
θ
julia> (1 * 21) + (2 * 22) +  (3 * 23)
134

The two arguments must have the same length. You can also use the dot operator, which you can obtain in the REPL by typing "\cdot" followed by a tab:

julia> [1:3] ⋅ [21:23]
134

連接數組和矩陣

[編輯]

You can use hcat() and vcat() to join matrices together, if their dimensions permit.

hcat() keeps the first dimension and extends (joins) in the second, vcat() keeps the second dimension and extends the first.

Here are two 3 by 4 matrices:

julia> A = reshape(1:12, 3, 4)
3x4 Array{Int64,2}:
 1  4  7  10
 2  5  8  11
 3  6  9  12
julia> B = reshape(100:100:1200, 3, 4)
3x4 Array{Int64,2}:
 100  400  700  1000
 200  500  800  1100
 300  600  900  1200

hcat(A, B) makes a new array that still has 3 rows, but extends/joins the columns to make 8 in total:

julia> hcat(A, B)
3x8 Array{Int64,2}:
 1  4  7  10  100  400  700  1000
 2  5  8  11  200  500  800  1100
 3  6  9  12  300  600  900  1200

vcat(A, B) makes a new array that keeps the 4 columns, but extends to 6 rows:

julia> vcat(A, B)
6x4 Array{Int64,2}:
   1    4    7    10
   2    5    8    11
   3    6    9    12
 100  400  700  1000
 200  500  800  1100
 300  600  900  1200

You'll probably find the shortcuts useful:

  • [A ; B ] is vcat(A, B)
  • [A B ] is hcat(A, B)

vec() flattens a matrix into a vector, turning it into a (what some call a 'column') vector:

 julia> vec(ones(3, 4))
12-element Array{Float64,1}:
 1.0
 1.0
 1.0
 1.0
 1.0
 1.0
 1.0
 1.0
 1.0
 1.0
 1.0
 1.0

There's also an hvcat() function ([A B; C D;]) that does both.

You can use hcat() to convert an array of arrays to a matrix (using the hcat-splat):

julia> a = Array[[1, 2], [3, 4], [5, 6]]
3-element Array{Array{T,N},1}:
 [1, 2]
 [3, 4]
 [5, 6]

julia> hcat(a...)
2x3 Array{Int64,2}:
 1  3  5
 2  4  6

Julia arrays are 'column-major'. This means that you read down the columns:

 1  3
 2  4

whereas 'row-major' arrays are to be read across, like this:

 1  2
 3  4

Column-major order is used in Fortran, R, Matlab, GNU Octave, and by the BLAS and LAPACK engines (the "bread and butter of high-performance numerical computation"). Row-major order is used in C/C++, Mathematica, Pascal, Python, C#/CLI/.Net and others.

增廣和擴展數組

[編輯]

Often you want to create an array and then add more to it, or 'grow' it. While can do this with vcat() and hcat(), be aware that both these operations create new temporary arrays and copy elements, so they don't always produce the fastest code. A better way is to use push!. This is an efficient operation that extends the array. You can reshape the array later:

julia> a = []
julia> for i = 1:80
    push!(a, i)
end

julia> a
80-element Array{Any,1}:
  1
  2
  3
  4
  5
  6
  7
  8
  9
  ⋮
 75
 76
 77
 78
 79
 80

reshape() lets you change the dimensions of an array. You can supply the dimensions or use a colon (:) to ask Julia to calculate valid dimensions:

julia> reshape(a, 10, :)
10x8 Array{Any,2}:
  1  11  21  31  41  51  61  71
  2  12  22  32  42  52  62  72
  3  13  23  33  43  53  63  73
  4  14  24  34  44  54  64  74
  5  15  25  35  45  55  65  75
  6  16  26  36  46  56  66  76
  7  17  27  37  47  57  67  77
  8  18  28  38  48  58  68  78
  9  19  29  39  49  59  69  79
 10  20  30  40  50  60  70  80

reshape(a, (10, div(length(a), 10))) would have the same effect.

push!() doesn't let you push new rows to a 2D array or matrix. The best way to do the job is to work on a 1D array, as above, adding more elements at the end, and then use reshape() to convert it to two dimensions. If necessary, use transpose() to flip the matrix.

操作矩陣

[編輯]

To transpose an array or matrix, there's an equivalent ' operator for the transpose() function, to swap rows and columns:

julia> M = reshape(1:12, 3, 4)
3×4 Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}}:
 1  4  7  10
 2  5  8  11
 3  6  9  12
julia> transpose(M)
4x3 Array{Int64,2}:
  1   2   3
  4   5   6
  7   8   9
 10  11  12
julia> M' 
4x3 Array{Int64,2}:
  1   2   3
  4   5   6
  7   8   9
 10  11  12

To find the determinant of a square matrix, use det(), after remembering to load the LinearAlgebra library.

julia> using LinearAlgebra
julia> A = rand(2:10, 3, 3)
3x3 Array{Int64,2}:
 8  8   2
 6  9   6
 9  2  10
julia> det(A)
438.00000000000006

inv() (in the Standard Library) finds the inverse of a square matrix, if it has one. (If the determinant of the matrix is zero, it won't have an inverse.)

julia> inv(A)
3x3 Array{Float64,2}:
  0.178082   -0.173516   0.0684932
 -0.0136986   0.141553  -0.0821918
 -0.157534    0.127854   0.0547945

LinearAlgebra.rank() finds the rank of the matrix, and LinearAlgebra.nullspace() finds the basis for the nullspace.

julia> A
3x4 Array{Int64,2}:
 1  4  7  10
 2  5  8  11
 3  6  9  12
julia> rank(A)
2
julia> nullspace(A)
4x2 Array{Float64,2}:
 -0.475185  -0.272395
  0.430549   0.717376
  0.564458  -0.617566
 -0.519821   0.172585

LinearAlgebra.tr() sums the diagonal of a square matrix (trace):

julia> s = reshape(1:9, 3, 3)
3x3 Array{Int64,2}:
 1  4  7
 2  5  8
 3  6  9
julia> tr(s)
15

對矩陣調用函數

[編輯]

There are a number of functions that can be applied to a matrix:

- sum() adds every element:

julia> A = reshape(1:9, 3, 3)
3×3 Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}}:
 1  4  7
 2  5  8
 3  6  9
julia> sum(A)
45

You can specify a dimension if you want to sum just columns or rows. So to sum columns, specify dimension 1:

julia> sum(A, dims=(1))
1x3 Array{Int64,2}:
 6  15  24

To sum rows, specify dimension 2:

julia> sum(A, dims=(2))
3x1 Array{Int64,2}:
 12
 15
 18

- mean() finds the mean of the values in the matrix:

julia> using Statistics; mean(A)
5.0

As with sum(), you can specify a dimension, so that you can find the mean of columns (use dimension 1) or rows (use dimension 2):

julia> mean(A, dims=(1))
1x3 Array{Float64,2}:
 2.0  5.0  8.0
julia> mean(A, dims=(2))
3x1 Array{Float64,2}:
 4.0
 5.0
 6.0

- the min(A, B) and max(A, B) functions compare two (or more) arrays element by element, returning a new array with the largest (or smallest) values from each:

julia> A = rand(-1:2:1, 3, 3)
3x3 Array{Int64,2}:
 -1  -1  -1
 -1   1   1
  1  -1   1
julia> B = rand(-2:4:2, 3, 3)
3x3 Array{Int64,2}:
 2   2  2
 2  -2  2
 2   2  2

prod() multiplies a matrix's elements together:

julia> A = reshape(collect(BigInt(1):25), 5, 5)
5×5 Array{BigInt,2}:
 1   6  11  16  21
 2   7  12  17  22
 3   8  13  18  23
 4   9  14  19  24
 5  10  15  20  25

julia> prod(A)
15511210043330985984000000

(Notice the use of BigInt, products are very large.)

You can specify a dimension if you want to multiply just columns or rows. To multiply the elements of columns together, specify dimension 1; for rows, use dimension 2:

julia> prod(A, 1)
1x5 Array{Int64,2}:
 120  30240  360360  1860480  6375600
julia> prod(A, 2)
5x1 Array{Int64,2}:
  22176
  62832
 129168
 229824
 375000

矩陣範數

[編輯]

大多數矩陣的函數在 LinearAlgebra 庫中:

julia> using LinearAlgebra

向量範數

[編輯]

向量的歐幾里得範數, , 在 LinearAlgebra.norm(x):

julia> X = [2, 4, -5]
3-element Array{Int64,1}:
  2
  4
 -5
 
julia> LinearAlgebra.norm(X) # Euclidean norm
6.708203932499369

julia> LinearAlgebra.norm(x, 1) # 1-norm of the vector, the sum of element magnitudes
11.0

如果 X 是一個 '行' 向量:

julia> X = [2 4 -5]
1x3 Array{Int64,2}:
 2  4  -5

julia> LinearAlgebra.norm(X)
6.708203932499369

julia> LinearAlgebra.norm(X, 1)
5.0

對於向量 和 向量 之間的歐幾里得距離 , is found by norm(x - y):

julia> LinearAlgebra.norm([1 2 3] - [2 4 6])
3.741657386773941

julia> LinearAlgebra.norm([1, 2, 3] - [2, 4, 6])
3.741657386773941

The angle between two vectors and is :

acos(dot(a,b)/(norm(a)*norm(b)))

矩陣範數

[編輯]

Here's the 1-norm of a matrix (the maximum absolute column sum):

julia> B = [5 -4 2 ; -1 2 3; -2 1 0]
3x3 Array{Int64,2}:
  5  -4  2
 -1   2  3
 -2   1  0
julia> LinearAlgebra.norm(B, 1)
8.0

And here's the infinity norm (the maximum absolute row sum):

julia> LinearAlgebra.norm(B, Inf)
11.0

The Euclidean norm() is the default:

julia> LinearAlgebra.norm([2 3 ; 4 6]), sqrt(2^2 + 3^2 + 4^2 + 6^2)
(8.062257748298547,8.06225774829855)

Scaling and rotating matrices

[編輯]

- rmul!(A, n) scales every element of the matrix in place by a scale factor n:

julia> A = [1 2 3  
            4 5 6  
            7 8 9] 
3×3 Array{Int64,2}:
 1  2  3
 4  5  6
 7  8  9

julia> rmul!(A, 2)
3×3 Array{Int64,2}:
  2   4   6
  8  10  12
 14  16  18

There are rotation and circular-shifting functions too:

julia> A = [1 2 3  
            4 5 6  
            7 8 9] 
3×3 Array{Int64,2}:
 1  2  3
 4  5  6
 7  8  9
julia> rot180(A)
3×3 Array{Int64,2}:
 9  8  7
 6  5  4
 3  2  1
julia> circshift(A, (1, 1))
3×3 Array{Int64,2}:
 9  7  8
 3  1  2
 6  4  5
julia> A
3×3 Array{Int64,2}:
 1  2  3
 4  5  6
 7  8  9

reverse() makes a copy of a matrix reversing rows or columns:

julia> reverse(A, dims=(1))
3×3 Array{Int64,2}:
 7  8  9
 4  5  6
 1  2  3
julia> reverse(A, dims=(2))
3×3 Array{Int64,2}:
 3  2  1
 6  5  4
 9  8  7

squeeze() and reshape() can be used to change the dimensions of a matrix. For example, this is how you can use squeeze() to collapse a row vector (1 by 4) into a 4 by 1 array:

julia> a = [1 2 3 4]
1x4 Array{Int64,2}:
1  2  3  4
julia> ndims(a)
2
julia> b = squeeze(a, dims=(1))
4-element Array{Int64,1}:
 1
 2
 3
 4
julia> ndims(b)
1

數組排序

[編輯]

Julia has a flexible sort() function that returns a sorted copy of an array, and a companion sort!() version that changes the array so that it's sorted.

You can usually use sort() without options and obtain the results you'd hoped for:

julia> using Random
julia> rp = randperm(10)
10-element Array{Int64,1}:
 6
 4
 7
 3
10
 5
 8
 1
 9
 2
julia> sort(rp)
10-element Array{Int64,1}:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10

You can sort 2D arrays:

julia> a = reshape(rand(1:20, 20), 4, 5)
4x5 Array{Int64,2}:
19  13   4  10  10
 6  20  19  18  12
17   7  15  14   9
 1  16   8   7  13
julia> sort(a, dims=(1)) # sort each column, dimension 1
4x5 Array{Int64,2}:
 1   7   4   7   9
 6  13   8  10  10
17  16  15  14  12
19  20  19  18  13
julia> sort(a, dims=(2)) # sort each row, dimension 2
4x5 Array{Int64,2}:
4  10  10  13  19
6  12  18  19  20
7   9  14  15  17
1   7   8  13  16

although there are more powerful alternatives in sortrows() and sortcolumns() — see below for details.

The sortperm() function is similar to sort(), but it doesn't return a sorted copy of the collection. Instead it returns a list of indices that could be applied to the collection to produce a sorted version:

julia> r = rand(100:110, 10)
10-element Array{Int64,1}:
 103
 102
 110
 108
 108
 108
 104
 109
 106
 106
julia> sortperm(r)
10-element Array{Int64,1}:
  2
  1
  7
  9
 10
  4
  5
  6
  8
  3
julia> r[sortperm(r)] 
10-element Array{Int64,1}:
 102
 103
 104
 106
 106
 108
 108
 108
 109
 110

排序和比較

[編輯]

If you need more than the default sort() offers, use the by and lt keywords and provide your own functions for processing and comparing elements during the sort.

sort by
[編輯]

The by function processes each element before comparison and provides the 'key' for the sort. A typical example is the task of sorting a list of numbers in string form into numerical order. Here's the list:

julia> r = ["1E10", "150", "25", "3", "1.5", "1E-10", "0.5", ".999"];

If you use the default sort, the numbers appear in the order in which the characters appear in Unicode/ASCII:

julia> sort(r)
8-element Array{ASCIIString,1}:
 ".999"
 "0.5"
 "1.5"
 "150"
 "1E-10"
 "1E10"
 "25"
 "3"

with "1E-10" appearing after "0.999".

To sort the numbers by their value, pass the parse() function (from the Meta package) to by:

julia> sort(r, by = x -> Meta.parse(x))
8-element Array{String,1}:
 "1E-10"
 "0.5"  
 ".999" 
 "1.5"  
 "3"    
 "25"   
 "150"  
 "1E10" 

The strings are sorted 'by' their value. Notice that the by function you supply produces the numerical sort key, but the original string elements appear in the final result.

Anonymous functions can be useful when sorting arrays. Here's a 10 rows by 2 columns array of tuples:

julia> table = collect(enumerate(rand(1:100, 10)))
10-element Array{(Int64,Int64),1}:
(1,86) 
(2,25) 
(3,3)  
(4,97) 
(5,89) 
(6,58) 
(7,27) 
(8,93) 
(9,98) 
(10,12)

You can sort this array by the second element of each tuple, not the first, by supplying an anonymous function to by that points to the second element of each. The anonymous function says, given an object x to sort, sort by the second element of x:

julia> sort(table, by = x -> x[2])
10-element Array{(Int64,Int64),1}:
(3,3)  
(10,12)
(2,25) 
(7,27) 
(6,58) 
(1,86) 
(5,89) 
(8,93) 
(4,97) 
(9,98)
Sorting by multiple columns
[編輯]

You can supply a tuple of "column" identifiers in the by function, if you want to sort by more than one column.

julia>  a = [[2, 2, 2, 1],
             [1, 1, 1, 8],
             [2, 1, 2, 2],
             [1, 2, 2, 5],
             [2, 1, 1, 4],
             [1, 1, 2, 7],
             [1, 2, 1, 6],
             [2, 2, 1, 3]] ;
julia> sort(a, by = col -> (col[1], col[2], col[3]))
8-element Array{Array{Int64,1},1}:
 [1,1,1,8]
 [1,1,2,7]
 [1,2,1,6]
 [1,2,2,5]
 [2,1,1,4]
 [2,1,2,2]
 [2,2,1,3]
 [2,2,2,1]

This sorts the array first by column 1, then by column 2, then by column 3.

Redefining 'less than'
[編輯]

By default, sorting uses the built-in isless() function when comparing elements. In a sorted array, the first element is less than the second.

You can change this behaviour by passing a different function to the lt keyword. This function should compare two elements and return true if they're sorted, i.e. if the first element is 'less than' the second, using some definition of 'less than'. The sorting process compares pairs of elements repeatedly until every element of the array is in the right place.

For example, suppose you want to sort an array of words according to the number of vowels in each word; i.e. the more vowels a word has, the earlier in the sorted results it occurs. For example, the word "orange" will be considered to be "less than" the word "lemon", because it has more vowels.

First we'll need a function that counts vowels:

vowelcount(string) = count(c -> (c in "aeiou"), lowercase(string))

Now you can pass an anonymous function to sort() that compares the vowel count of two elements using this function and then returns the element with a higher count in each case:

 sentence = split("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.");
 sort(sentence, lt = (x,y) -> vowelcount(x) > vowelcount(y))

The result is that the word with the most vowels appears first:

19-element Array{SubString{String},1}:

"adipisicing"
"consectetur"
"eiusmod"    
"incididunt" 
"aliqua."    
"labore"     
"dolore"     
"Lorem"      
"ipsum"      
"dolor"      
"amet,"      
"elit,"      
"tempor"     
"magna"      
"sit"        
"sed"        
"do"         
"ut"         
"et"         

The sort() function also lets you specify a reverse sort - after the by and lt functions (if used) have done their work, a true value passed to rev reverses the result.

二維數組排序

[編輯]

In Julia 1.0, you can sort multidimensional arrays with sortslices().

Here's a simple array of nine strings (you can also use numbers, symbols, functions, or anything that can be compared):

julia> table = ["F" "B" "I"; "A" "D" "G"; "H" "C" "E"]
3×3 Array{String,2}:
 "F"  "B"  "I"
 "A"  "D"  "G"
 "H"  "C"  "E"

You supply a number or a tuple to the dims ("dimensions") keyword that indicates what you want to sort. To sort the table so that the first column is sorted, use 1:

julia> sortslices(table, dims=1)
3×3 Array{String,2}:
 "A"  "D"  "G"
 "F"  "B"  "I"
 "H"  "C"  "E"

Note that sortslices returns a new array. The first column is in alphabetical order.

Use dims=2 to sort the table so that the first row is sorted:

julia>> sortslices(table, dims=2)
3×3 Array{String,2}:
 "B"  "F"  "I"
 "D"  "A"  "G"
 "C"  "H"  "E"

Now the first row is in alphabetical order.

If you want to sort by something other than the first item, pass a function to by. So, to sort rows so that the middle column is in alphabetical order, use:

julia> sortslices(table, dims=1, by = x -> x[2])
3×3 Array{String,2}:
 "F"  "B"  "I"
 "H"  "C"  "E"
 "A"  "D"  "G"

sortslices has most of the options that you'll find in sort, and more besides. You can reverse the order with rev, change the comparator with lt, and so on.

元組

[編輯]

A tuple is an ordered sequence of elements, like an array. A tuple is represented by parentheses and commas, rather than the square brackets used by arrays. Tuples are mostly good for small fixed-length collections — they're used everywhere in Julia, for example, as argument lists and for returning multiple values from functions.

The important difference between arrays and tuples is that tuples are immutable. Other than that, tuples work in much the same way as arrays, and many array functions can be used on tuples too:

julia> t = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
(1,2,3,4,5,6,7,8,9,10)
julia> t
(1,2,3,4,5,6,7,8,9,10)
julia> t[6:end]
(6,7,8,9,10)

You can have two-dimensional tuples:

julia> t = ((1, 2), (3, 4))
((1,2),(3,4))
julia> t[1]
(1,2)
julia> t[1][2]
2

But you can't change a tuple:

julia> t[1] = 0
LoadError: MethodError: no method matching set index!...

And, because you can't modify tuples, you can't use any of the functions like push!() that you use with arrays:

julia> a = [1,2,3];
julia> push!(a,4)
4-element Array{Int64,1}:
1
2
3
4
julia> t = (1,2,3);
julia> push!(t,4)
LoadError: MethodError: no method matching push!

命名的元組

[編輯]

A named tuple is like a combination of a tuple and a dictionary. Like a tuple, a named tuple is ordered and immutable, and enclosed in parentheses; like a dictionary, each element has a unique key that can be used to access it.

You can create a named tuple by providing keys and values directly:

julia> shape1 = (corner1 = (1, 1), corner2 = (-1, -1), center = (0, 0))

(corner1 = (1, 1), corner2 = (-1, -1), center = (0, 0))

To access the values, use the familiar dot syntax:

julia> shape1.corner1
(1, 1)

julia> shape1.center
(0, 0)

julia> (shape1.corner1, shape1.corner2)
((1, 1), (-1, -1))

You can access all the values (destructuring) as with ordinary tuples:

julia> c1, c2, centerp = shape1;

julia> c1
(1, 1)

julia> c2
(-1, -1)

or just some of them:

julia> c1, c2 = shape1;

julia> c1
(1, 1)
julia> c2
(-1, -1)

Elements can be the same type, or different types, but the keys will always be variable names.

You can iterate over a named tuple:

julia> for i in shape1
         @show i
       end

i = (1, 1)
i = (-1, -1)
i = (0, 0)

julia> for i in shape1
           println(first(i))
       end

1
-1
0

Another way to create a named tuple is to provide the keys and values in separate tuples:

julia> ks = (:corner1, :corner2)
(:corner1, :corner2)

julia> vs = ((10, 10), (20, 20))
((10, 10), (20, 20))

julia> shape2 = NamedTuple{ks}(vs)
(corner1 = (10, 10), corner2 = (20, 20))

julia>shape2.corner1
(10, 10)

julia> shape2.corner2
(20, 20)

You can combine two named tuples to make a new one:

julia> colors = (top = "red", bottom = "green")
(top = "red", bottom = "green")

julia> merge(shape2, colors)
(corner1 = (10, 10), corner2 = (20, 20), top = "red", bottom = "green")

You can use existing variables for keys:

julia> d = :density;

julia> (corner1 = (10, 10), corner2 = (20, 20), d => 0.99)
(corner1 = (10, 10), corner2 = (20, 20), density = 0.99)

Making single value Named Tuples requires a strategically-placed comma:

julia> shape3 = (corner1 = (1, 1),)

(corner1 = (1, 1),)
julia> typeof(shape3)
 NamedTuple{(:corner1,),Tuple{Tuple{Int64,Int64}}}

If you forget it, you'll see this:

julia> (corner1 = (1, 1))
(1, 1)

julia> typeof(corner1)
Tuple{Int64,Int64}

You can make new named tuples by combining named tuples together.

julia> shape3 = merge(shape2, colors)
(corner1 = (10, 10), corner2 = (20, 20), top = "red", bottom = "green")

Use a comma after a single element named tuple:

julia> merge(shape2, (top = "green",))
(corner1 = (10, 10), corner2 = (20, 20), top = "green")

因為沒有逗號,元組將被解釋為 merge() 的帶圓括號的關鍵字參數。

To iterate over the "keys", use the fieldnames() and typeof() functions:

julia> fieldnames(typeof(shape3))
(:corner1, :corner2, :top, :bottom)

so you can do:

julia> for key in fieldnames(typeof(shape3))
     @show getindex(shape3, key)
 end

getindex(shape3, key) = (10, 10)
getindex(shape3, key) = (20, 20)
getindex(shape3, key) = "red"
getindex(shape3, key) = "green"

合併兩個元組是明智的。例如,如果您有以下命名的元組:

julia> shape3
(corner1 = (10, 10), corner2 = (20, 20), top = "red", bottom = "green")

並且要添加中心點並更改頂部顏色:

julia> merge(shape3, (center = (0, 0), top="green"))

(corner1 = (10, 10), corner2 = (20, 20), top = "green", bottom = "green", center = (0, 0))

將插入新值,並更改現有值。

« Introducing Julia
Arrays and tuples
»
The REPL Types