介绍 Julia/数组和元组
在 Julia 中,相关项目的组通常存储在数组、元组或字典中。数组可用于存储向量和矩阵。本节重点介绍数组和元组;有关字典的更多信息,请参阅 字典和集合。
数组是有序的元素集合。它通常用方括号和逗号分隔的项目表示。您可以创建完整的或空的数组,以及包含不同类型值的数组或仅包含特定类型的数组。
在 Julia 中,数组用于列表、向量、表格和矩阵。
一维数组充当向量或列表。二维数组可以用作表格或矩阵。三维和更多维数组类似地被认为是多维矩阵。
以下是创建简单一维数组的方法
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 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
如果您认为可以在声明类型化数组时偷偷潜入一个错误类型的 value,那么您将被发现
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 维或更多维的数组/矩阵。
有许多函数可以让您一次创建并填充数组。请参阅 创建和填充数组。
请注意 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
和 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 中,冒号 (:
) 有多种用途。其中一个用途是定义数字的范围和序列。你可以直接输入来创建一个范围对象
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
要向下而不是向上,你必须使用负的步长值
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()
,它构造一个范围对象,该对象从一个起始值到一个结束值,以特定的步长大小执行特定数量的步长。你不需要计算所有信息,因为 Julia 会通过组合 step
、length
和 stop
关键字的值来为你计算缺失的部分。例如,要以 12 步长从 1 到 100
julia> range(1, length=12, stop=100) 1.0:9.0:100.0
或者以 10 步长从 1 开始,停止在 100 或之前
julia> range(1, stop=100, step=10) 1:10:91
如果你真的想要以数组形式,你可以使用范围对象来构建数组
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 数组,而不是一个 Integer 数组,即使这些值可以是整数。
对于对数范围(有时称为“对数空间”),你可以使用简单的范围对象,然后将 exp10
函数 (10^x
) 广播到范围的每个元素。
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
请参阅广播和点语法。
对范围对象使用 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
如你所见,如果你不在 for
循环中使用范围对象,如果你愿意,可以使用 collect()
直接从范围对象中获取所有值
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
一种创建数组的实用方法,其中每个元素都可以使用一个小计算来生成,是使用推导(在推导中描述)。
例如,要创建一个包含 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)
创建一个具有 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)
创建一个包含均值为 0、标准差为 1 的正态分布随机数字的 m 行 n 列矩阵。
除了 zeros()
、ones()
函数之外,还有 trues()
、falses()
、fill()
和 fill!()
函数。
trues()
和 falses()
函数用布尔值真或假填充数组
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
和 outer
选项确定是否重复行和/或列。例如,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()
函数为你构建特定类型的数组
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
复制数组
[edit | edit source]如果您已有数组,并希望创建另一个具有相同维度的数组,可以使用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()
函数。
矩阵运算:将数组用作矩阵
[edit | edit source]在 Julia 中,二维数组可以作为矩阵使用。所有用于处理数组的函数都可以使用(如果维度和内容允许)作为矩阵。
键入矩阵的快捷方式是使用空格分隔元素(形成行),并使用分号分隔行。所以
julia> [1 0 ; 0 1]
2x2 Array{Int64,2}:
1 0
0 1
|
|
你也可以这样做
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
访问数组的内容
[edit | edit source]要访问数组或矩阵的元素,请在数组名称后面用方括号加上元素编号。这是一个一维数组
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 为基准的索引器阵营中。)
最后一个元素被称为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
您甚至可以使用true
和false
值来选择元素
julia> a[[true, true, false, true, true, true, false, true, false, false]] 6-element Array{Int64,1}: 10 20 40 50 60 80
这是一个二维数组,行用分号分隔
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
如果您只要求一个二维数组的元素,您将收到它,就像数组被按列展开一样,即先向下,然后横向。在这种情况下,您将得到 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
逐元素和向量化运算
[edit | edit source]许多 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
并且结果的第一个元素是两个数组的第一个元素相乘的结果,依此类推。
除了算术运算符之外,一些比较运算符也有逐元素版本。例如,与其在循环中使用==
比较两个数组,不如使用.==
。这里有两个十个数的数组,一个是连续的,另一个是无序的,以及一个逐元素比较,以查看数组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
广播:用于向量化函数的点语法
[edit | edit source]这种使用点语法将函数逐元素应用于数组的技术称为广播。在函数名称后面加上一个点/句号,然后是左括号,并将数组或范围作为参数提供。例如,这里有一个简单的函数,它将两个数字相乘
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 自动将第二个参数视为数组,以便乘法能够正确地工作。
在组合范围和向量化函数时要注意这一点
julia> 0:10 .* 0.5 |> collect 6-element Array{Float64,1}: 0.0 1.0 2.0 3.0 4.0 5.0 julia> 0.5 .* 0:10 |> collect 11-element Array{Float64,1}: 0.0 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0
第一个示例等效于0:(10 .* 0.5)
,您可能想要(0:10) .* 0.5
。
min() 和 max()
[edit | edit source]注意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()
的行为类似。
使max在数组上起作用的方法是使用省略号(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
返回一个包含true
和false
值的数组,然后使用这些值选择要设置为 11 的a
元素。
如果您正在对二维矩阵进行算术运算,您可能需要阅读有关矩阵算术的更多信息:矩阵算术
行和列
[edit | edit source]对于二维数组,您可以使用括号、冒号和逗号来提取单个行和列或行和列的范围。
使用此表
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
在数组中查找项目
[edit | edit source]如果您想知道数组是否包含一个项目,请使用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
请记住,这些是索引编号的数组,而不是实际的单元格值。可以使用这些索引来提取相应的 value,使用标准的方括号语法
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
要返回数组 B 中元素的索引,其中数组 A 的元素可以找到,请使用 findall(in(A), B)
julia> findall(in([11, 5]), smallprimes) 2-element Array{Int64,1}: 3 5 julia> smallprimes[3] 5 julia> smallprimes[5] 11
应注意返回索引的顺序。
使用我们的二维数组
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
要查找数组/矩阵的逆矩阵、行列式和其他方面,请参见 操作矩阵。
要将索引号(1 到 n
)和行/列号(1:r
,1:c
)相互转换,可以使用
julia> CartesianIndices(a2)[6] CartesianIndex(3, 2)
例如,要查找第六个元素的行和列。
要反过来操作,第 3 行第 2 列对应哪个索引号?使用笛卡尔索引的相反形式,线性索引
julia> LinearIndices(a2)[3, 2] 6
diff()
用于查找数组中每个元素之间的差值
julia> [2x for x in 1:10] 10-element Array{Int64,1}: 2 4 6 8 10 12 14 16 18 20 julia> [2x for x in 1:10] |> diff 9-element Array{Int64,1}: 2 2 2 2 2 2 2 2 2
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()
查找并保留通过测试的元素。在这里,我们使用 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)
使用 argmax()
仅返回索引。
maximum()
和 minimum()
函数允许你提供函数来确定如何确定“最大值”。如果你数组不是简单的向量,这将非常有用。此示例查找最大数组元素,其中“最大”是指“具有最大最后值”
julia> maximum(x -> last(x), [(1, 2), (2, 23), (8, 12), (7, 2)]) 23
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()
和 prod()
也允许你提供函数:该函数应用于每个元素,然后对结果进行求和/求平均值/求积
julia> sum(sqrt, 1:10) # the sum of the square roots of the first 10 integers 22.4682781862041 julia> mean(sqrt, 1:10) # the mean of the square roots of the first 10 integers 2.24682781862041
Combinatorics.jl 包中有一些函数,可以让你查找数组的组合和排列。combinations()
查找数组中元素的所有可能组合:你可以指定每个组合中的元素数量
julia> ] (v1.0) 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
像往常一样,感叹号提醒你此函数会更改数组。你只能向向量末尾添加项目。
要将项目添加到开头,请使用 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
可以使用 deleteat!()
和 splice!()
等函数对数组(以及类似的数据结构)进行更激进的修改。你可以通过多种方式找出元素的索引。一旦你知道了索引,就可以使用 deleteat!()
删除元素,方法是提供其索引号
julia> a = collect(1:10);
julia> findfirst(isequal(6), a) 6
julia> deleteat!(a, findfirst(isequal(6), a)) 9-element Array{Int64,1}: 1 2 3 4 5 7 8 9 10
deleteat!()
也接受一个范围或迭代器来指定索引,因此你可以这样做
julia> deleteat!(a, 2:6) 4-element Array{Int64,1}: 1 8 9 10
请记住,你始终可以使用过滤器删除一组元素:请参见 过滤。
如果你想对数组做一些操作,可能会有一个函数可以做到,而且有时会带有一个感叹号来提醒你潜在的后果。以下是一些其他此类数组修改函数
resize!()
更改向量的长度append!()
将第二个集合推送到第一个集合的后面prepend!()
在第一个向量的开头插入元素empty!(a)
删除所有元素unique(a)
从数组“a”中删除重复元素,但不覆盖数组。unique!(a)
从数组“a”中删除重复元素,并覆盖数组。rotr90(a)
复制一个数组,并将其顺时针旋转 90 度
julia> rotr90([1 2 3 ; 4 5 6]) 3x2 Array{Int64,2}: 4 1 5 2 6 3
circshift(a)
将元素“循环”移动一定步数
julia> circshift(1:6, 1) 6-element Array{Int64,1}: 6 1 2 3 4 5
此函数也可以对二维数组进行循环移位。例如,这是一个表格
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
通过提供一个元组,你可以移动行和列。例如:将列移动 0 步,将行移动 1 步,会将第一维移动 0 步,第二维移动 1 步。第一维向下,第二维向右
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
circshift()
还有一个修改版本,circshift!
设置数组的内容
[edit | edit source]要设置数组的内容,在赋值表达式的左侧指定索引
julia> a = collect(1:10); julia> a[9]= -9 -9
要检查数组是否真的发生了改变
julia> print(a) [1,2,3,4,5,6,7,8,-9,10]
你可以使用广播赋值运算符一次性设置多个元素
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]
你还可以将一系列元素设置为适合的一系列值
julia> a[3:9] = collect(9:-1:3) 7-element Array{Int64,1}: 9 8 7 6 5 4 3
注意,虽然 Julia 显示 7 元素切片作为返回值,但实际上整个数组已被修改
julia> a 10-element Array{Int64,1}: 1 2 9 8 7 6 5 4 3 10
可以使用广播将范围设置为单个值
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]
作为方括号表示法的替代方法,有一个函数调用版本可以完成相同的设置数组内容的工作,setindex!()
julia> setindex!(a, 1:10, 10:-1:1) 10-element Array{Int64,1}: 10 9 8 7 6 5 4 3 2 1
你可以使用冒号分隔符而不带起始和结束索引号来引用数组的全部内容,即 [:]
。例如,创建数组 a
后
julia> a = collect(1:10);
我们可以使用 a[:]
来引用该数组 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
将数组传递给函数
[edit | edit source]函数无法修改作为参数传递给它的变量,但可以改变传递给它的容器的内容。
考虑以下函数,它将它的参数更改为 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
如果你尝试改变变量本身,而不是访问容器变量的内容,它将不起作用。例如,以下函数定义在 temp
中创建一个由 5 组成的数组,然后尝试将参数 x
更改为 temp
。
julia> function fail_to_fill_with_5(x)
temp = similar(x)
for i in eachindex(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
看起来它工作了,但是
julia> x 10-element Array{Int64,1}: 1 2 3 4 5 6 7 8 9 10
你可以改变数组中的元素,但你不能改变变量,使其指向另一个数组。换句话说,你的函数不允许改变参数和传递给它的数组之间的绑定。
Julia 处理函数参数的方式被称为“按共享传递”。当你将数组传递给函数时,它不会被复制(对于大型数组来说,这将非常低效)。
矩阵运算
[edit | edit source]对于矩阵对矩阵的运算,你可以
- 加 (+) 和减 (-)
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 = ones(3,4)
3x4 Array{Float64,2}:
1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0
|
|
julia> A + B
3x4 Array{Float64,2}:
2.0 5.0 8.0 11.0
3.0 6.0 9.0 12.0
4.0 7.0 10.0 13.0
|
|
julia> A - B
3x4 Array{Float64,2}:
0.0 3.0 6.0 9.0
1.0 4.0 7.0 10.0
2.0 5.0 8.0 11.0
|
|
- 乘 (*),假设维度兼容,因此 m1 * m2
是可能的,如果 last(size(m1)) == first(size(m2))
。注意矩阵乘法和元素级矩阵乘法之间的区别。这是一个矩阵 A
julia> A = [1 2 ; 3 4]
2x2 Array{Int64,2}:
1 2
3 4
|
|
还有矩阵 `B`
julia> B = [10 11 ; 12 13]
2x2 Array{Int64,2}:
10 11
12 13
|
|
.*
广播运算符逐元素相乘
julia> A .* B
2x2 Array{Int64,2}:
10 22
36 52
|
|
与矩阵乘法 `A * B` 相比
julia> A * B
2x2 Array{Int64,2}:
34 37
78 85
|
|
是
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
- 两个矩阵的除法。可以使用反斜杠 (\) 进行左除
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
以及正斜杠 (/) 进行右除或斜除
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
对于矩阵和标量,可以进行加、减、乘和除运算
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
等等
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
如果数组具有兼容的形状,则可以将矩阵乘以向量(矩阵向量积)。这是矩阵 A
julia> A = reshape(1:12, 3, 4)
3x4 Array{Int64,2}:
1 4 7 10
2 5 8 11
3 6 9 12
|
|
这是向量 V
julia> V = collect(1:4)
4-element Array{Int64,1}:
1
2
3
4
|
|
*
运算符将它们相乘
julia> A * V
3-element Array{Int64,1}:
70
80
90
|
|
可以使用 `dot()` 函数找到点积或内积 (aTb),但首先需要导入 LinearAlgebra 库
julia> using LinearAlgebra
julia> dot([1:3...], [21:23...])
134
|
|
julia> (1 * 21) + (2 * 22) + (3 * 23) 134
两个参数的长度必须相同。也可以使用点运算符,在 REPL 中,可以通过输入 "\cdot" 然后按 Tab 键获得点运算符
julia> [1:3] ⋅ [21:23] 134
连接数组和矩阵
[edit | edit source]如果矩阵的维度允许,可以使用 `hcat()` 和 `vcat()` 将它们连接在一起。
hcat()
保留第一维并扩展(连接)第二维,vcat()
保留第二维并扩展第一维。
这是两个 3×4 矩阵
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)
创建一个新的数组,该数组仍然具有 3 行,但扩展/连接列,使总列数为 8
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)
创建一个新的数组,该数组保留 4 列,但扩展到 6 行
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
你可能会发现快捷方式很有用
- [A ; B ] 是
vcat(A, B)
- [A B ] 是
hcat(A, B)
vec()
将矩阵扁平化为向量,将其转换为(有些人称之为“列”)向量
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
还有一个 `hvcat()` 函数 ([A B; C D;]
),它同时执行这两项操作。
可以使用 `hcat()` 将数组的数组转换为矩阵(使用 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 数组是“列优先”的。这意味着你从上到下读取列
1 3 2 4
而“行优先”数组是从左到右读取的,例如
1 2 3 4
Fortran、R、Matlab、GNU Octave 以及 BLAS 和 LAPACK 引擎(“高性能数值计算的核心”)使用列优先顺序。C/C++、Mathematica、Pascal、Python、C#/CLI/.Net 等语言使用行优先顺序。
扩展数组
[edit | edit source]通常,你希望创建一个数组,然后向其中添加更多元素或“扩展”它。虽然可以使用 vcat()
和 hcat()
完成此操作,但请注意,这两个操作都会创建新的临时数组并复制元素,因此它们并不总是能生成最快的代码。更好的方法是使用 `push!`。这是一个高效的操作,可以扩展数组。之后可以对数组进行重塑
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()
允许你更改数组的维度。可以提供维度,也可以使用冒号 (:
) 让 Julia 计算有效的维度
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)))
将产生相同的效果。
push!()
无法将新行推送到二维数组或矩阵。完成此任务的最佳方法是像上面一样操作一维数组,在末尾添加更多元素,然后使用 `reshape()` 将其转换为二维。如果需要,可以使用 `transpose()` 翻转矩阵。
要转置数组或矩阵,有一个等效的'
运算符用于transpose()
函数,用于交换行和列
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
要查找方阵的行列式,请使用det()
,在使用之前请记住加载LinearAlgebra库。
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()
(在标准库中)查找方阵的逆矩阵(如果存在)。(如果矩阵的行列式为零,则它将没有逆矩阵。)
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()
查找矩阵的秩,LinearAlgebra.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()
求和方阵的对角线(迹)
julia> s = reshape(1:9, 3, 3) 3x3 Array{Int64,2}: 1 4 7 2 5 8 3 6 9
julia> tr(s) 15
有许多函数可以应用于矩阵
- sum()
将所有元素加起来
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
如果要仅求和列或行,则可以指定一个维度。因此,要求和列,请指定维度 1
julia> sum(A, dims=(1)) 1x3 Array{Int64,2}: 6 15 24
要求和行,请指定维度 2
julia> sum(A, dims=(2)) 3x1 Array{Int64,2}: 12 15 18
- mean()
查找矩阵中值的平均值
julia> using Statistics; mean(A) 5.0
与 sum()
一样,您可以指定一个维度,以便可以查找列的平均值(使用维度 1)或行的平均值(使用维度 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
- min.(A, B)
和 max.(A, B)
函数逐元素比较两个(或更多)数组,返回一个包含每个元素中最大值(或最小值)的新数组
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 julia> min.(A, B) 3×3 Array{Int64,2}: 1 -2 -2 -1 -2 -1 1 1 -1 julia> max.(A, B) 3×3 Array{Int64,2}: 2 1 1 2 1 2 2 2 2
prod()
将矩阵的元素相乘
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
(注意 BigInt
的使用,乘积非常大。)
如果要仅将列或行的元素相乘,则可以指定一个维度。要将列的元素相乘,请指定维度 1;对于行,请使用维度 2
julia> prod(A, dims=1) 1x5 Array{Int64,2}: 120 30240 360360 1860480 6375600
julia> prod(A, dims=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) 11.0
向量 和 之间的欧几里得距离,由 给出,由 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
两个向量 和 之间的夹角为
acos(dot(a,b)/(norm(a)*norm(b)))
以下是矩阵的 1-范数(最大绝对列之和)
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.opnorm(B, 1) 8.0
以下是无穷范数(最大绝对行之和)
julia> LinearAlgebra.opnorm(B, Inf) 11.0
请注意,它们不同于向量化的 1-范数或无穷范数
julia> LinearAlgebra.norm(B, 1) 20.0
julia> LinearAlgebra.norm(B, Inf) 5.0
欧几里得 norm()
是默认值
julia> LinearAlgebra.norm([2 3 ; 4 6]), LinearAlgebra.opnorm([2 3 ; 4 6]), sqrt(2^2 + 3^2 + 4^2 + 6^2) (8.062257748298547,8.062257748298547,8.06225774829855)
- rmul!(A, n)
将矩阵的每个元素就地缩放一个缩放因子 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
还有旋转和循环移位函数
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()
会创建矩阵的副本,反转行或列
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()
和 reshape()
可用于更改矩阵的维度。例如,以下是如何使用 squeeze()
将行向量(1 x 4)压缩为 4 x 1 数组
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 具有灵活的 sort()
函数,该函数返回数组的已排序副本,还有一个配套的 sort!()
版本,该版本会更改数组使其已排序。
通常可以使用 sort()
而不使用任何选项,并获得期望的结果
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
您可以对二维数组进行排序
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
但 sortrows()
和 sortcolumns()
中有更强大的替代方法——有关详细信息,请参见下文。
sortperm()
函数类似于 sort()
,但它不返回集合的已排序副本。相反,它返回一个索引列表,可以应用于集合以生成已排序版本
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
如果需要超出默认 sort()
的功能,请使用 by
和 lt
关键字,并为排序期间的元素处理和比较提供自己的函数。
by
函数在比较之前会处理每个元素,并为排序提供“键”。一个典型的示例是将字符串形式的数字列表按数值顺序排序的任务。以下是该列表
julia> r = ["1E10", "150", "25", "3", "1.5", "1E-10", "0.5", ".999"];
如果使用默认排序,则数字将按 Unicode/ASCII 中字符出现的顺序显示
julia> sort(r) 8-element Array{ASCIIString,1}: ".999" "0.5" "1.5" "150" "1E-10" "1E10" "25" "3"
其中“1E-10”出现在“0.999”之后。
要按数字的值对其进行排序,请将 parse()
函数(来自 Meta 包)传递给 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"
字符串按其值排序。请注意,您提供的by
函数会生成数值排序键,但最终结果中会显示原始字符串元素。
匿名函数在排序数组时很有用。下面是一个 10 行 2 列的元组数组。
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)
您可以通过向by
提供一个指向每个元组第二元素的匿名函数,按每个元组的第二个元素而不是第一个元素对该数组进行排序。匿名函数表示,给定要排序的对象x
,按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)
按多列排序
[edit | edit source]如果您想按多列排序,可以在by
函数中提供一个“列”标识符元组。
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]
这将首先按列 1 排序数组,然后按列 2 排序,最后按列 3 排序。
重新定义“小于”
[edit | edit source]默认情况下,排序在比较元素时使用内置的isless()
函数。在排序后的数组中,第一个元素小于第二个元素。
您可以通过将不同的函数传递给lt
关键字来更改此行为。此函数应比较两个元素,如果它们已排序,则返回 true,即如果第一个元素“小于”第二个元素(使用某种“小于”定义)。排序过程会重复比较元素对,直到数组中的每个元素都处于正确位置。
例如,假设您想根据每个单词中的元音数量对单词数组进行排序;也就是说,元音数量越多的单词,在排序结果中出现的越早。例如,单词“orange”将被视为“小于”单词“lemon”,因为它包含更多元音。
首先,我们需要一个计算元音数量的函数
vowelcount(string) = count(c -> (c in "aeiou"), lowercase(string))
现在,您可以将一个匿名函数传递给sort()
,该函数使用此函数比较两个元素的元音数量,然后在每种情况下返回元音数量较多的元素
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))
结果是元音数量最多的单词将出现在最前面
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"
sort()
函数还允许您指定反向排序 - 在by
和lt
函数(如果使用)完成其工作后,传递给rev
的 true 值将反转结果。
排序二维数组
[edit | edit source]在 Julia 1.0 中,您可以使用sortslices()
对多维数组进行排序。
下面是一个包含九个字符串的简单数组(您也可以使用数字、符号、函数或任何可以比较的内容)
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"
您可以向dims
(“维度”)关键字提供一个数字或一个元组,以指示要排序的内容。要排序表以使第一列排序,请使用1
julia> sortslices(table, dims=1) 3×3 Array{String,2}: "A" "D" "G" "F" "B" "I" "H" "C" "E"
请注意,sortslices
会返回一个新数组。第一列按字母顺序排列。
使用dims=2
对表进行排序,以使第一行排序
julia>> sortslices(table, dims=2) 3×3 Array{String,2}: "B" "F" "I" "D" "A" "G" "C" "H" "E"
现在第一行按字母顺序排列。
如果您想按第一项以外的其他内容进行排序,请将一个函数传递给by
。因此,要按行排序,以使中间列按字母顺序排列,请使用
julia> sortslices(table, dims=1, by = x -> x[2]) 3×3 Array{String,2}: "F" "B" "I" "H" "C" "E" "A" "D" "G"
sortslices
具有您在sort
中找到的大多数选项,以及更多。您可以使用rev
反转顺序,使用lt
更改比较器,等等。
元组
[edit | edit source]元组是元素的有序序列,类似于数组。元组由圆括号和逗号表示,而不是数组使用的方括号。元组通常适合于小型固定长度的集合 - 它们在 Julia 中无处不在,例如作为参数列表以及从函数返回多个值。
数组和元组之间最重要的区别是元组是不可变的。除此之外,元组的工作方式与数组非常相似,许多数组函数也可以在元组上使用。
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)
您可以拥有二维元组
julia> t = ((1, 2), (3, 4)) ((1,2),(3,4))
julia> t[1] (1,2)
julia> t[1][2] 2
但是您无法更改元组
julia> t[1] = 0 LoadError: MethodError: no method matching set index!...
而且,由于您无法修改元组,因此您无法使用与数组一起使用的任何函数(例如push!()
)。
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!
命名元组
[edit | edit source]命名元组类似于元组和字典的组合。与元组一样,命名元组是有序且不可变的,并用圆括号括起来;与字典一样,每个元素都有一个唯一的键,可用于访问它。
您可以通过直接提供键和值来创建命名元组
julia> shape1 = (corner1 = (1, 1), corner2 = (-1, -1), center = (0, 0)) (corner1 = (1, 1), corner2 = (-1, -1), center = (0, 0))
要访问值,请使用熟悉的点语法
julia> shape1.corner1 (1, 1) julia> shape1.center (0, 0) julia> (shape1.corner1, shape1.corner2) ((1, 1), (-1, -1))
您可以像普通元组一样访问所有值(解构)
julia> c1, c2, centerp = shape1; julia> c1 (1, 1) julia> c2 (-1, -1)
或者只访问其中一些
julia> c1, c2 = shape1; julia> c1 (1, 1)
julia> c2 (-1, -1)
元素可以是相同类型,也可以是不同类型,但键始终是变量名。
您可以遍历命名元组
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
创建命名元组的另一种方法是在单独的元组中提供键和值
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)
您可以组合两个命名元组以创建一个新的命名元组
julia> colors = (top = "red", bottom = "green") (top = "red", bottom = "green") julia> merge(shape2, colors) (corner1 = (10, 10), corner2 = (20, 20), top = "red", bottom = "green")
您可以使用现有变量作为键
julia> d = :density; julia> (corner1 = (10, 10), corner2 = (20, 20), d => 0.99)
(corner1 = (10, 10), corner2 = (20, 20), density = 0.99)
创建单个值的命名元组需要一个策略性放置的逗号
julia> shape3 = (corner1 = (1, 1),) (corner1 = (1, 1),)
julia> typeof(shape3) NamedTuple{(:corner1,),Tuple{Tuple{Int64,Int64}}}
如果您忘记它,您将看到此提示
julia> (corner1 = (1, 1)) (1, 1) julia> typeof(corner1) Tuple{Int64,Int64}
您可以通过将命名元组组合在一起创建新的命名元组。
julia> shape3 = merge(shape2, colors) (corner1 = (10, 10), corner2 = (20, 20), top = "red", bottom = "green")
在单个元素命名元组之后使用逗号
julia> merge(shape2, (top = "green",)) (corner1 = (10, 10), corner2 = (20, 20), top = "green")
因为如果没有逗号,元组将被解释为merge()
的括号括起来的关键字参数。
要遍历“键”,请使用fieldnames()
和typeof()
函数
julia> fieldnames(typeof(shape3)) (:corner1, :corner2, :top, :bottom)
所以您可以执行以下操作
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))
将插入新值,并更改现有值。
使用命名元组作为关键字参数
[edit | edit source]命名元组是将一组关键字参数传递给函数的便捷方式。下面是一个接受三个关键字参数的函数
function f(x, y, z; a=10, b=20, c=30) println("x = $x, y = $y, z = $z; a = $a, b = $b, c = $c") end
您可以定义一个命名元组,其中包含一个或多个关键字的名称和值
options = (b = 200, c = 300)
要将命名元组传递给函数,请在调用函数时使用;
f(1, 2, 3; options...) x = 1, y = 2, z = 3; a = 10, b = 200, c = 300
如果您指定关键字和值,则它可以被后面的定义覆盖
f(1, 2, 3; b = 1000_000, options...) x = 1, y = 2, z = 3; a = 1000, b = 200, c = 300
f(1, 2, 3; options..., b= 1000_000) x = 1, y = 2, z = 3; a = 10, b = 1000000, c = 300