Julia 字典和集合
除了数组和元组,Julia 还提供了两种常用的集合:字典(Dict)和 Set(无序集合)。
字典
字典是一种可变容器模型,且可存储任意类型对象。
字典的每个键值对用 => 分割,每个键值对之间用逗号 , 分割,整个字典包括在花括号 {} 中。
创建字典
创建字典的语法格式如下:
Dict("key1" => value1, "key2" => value2, ..., "keyn" => valuen)
以下实例创建一个简单的字典,键 A 对应的值为 1,键 B 对应的值为 2:
实例
Dict{String, Int64} with 2 entries:
"B" => 2
"A" => 1
Julia 会自动推断键和值的类型,如上例为 Dict{String, Int64}。也可以显式指定类型:
实例
Dict{String, Float64} with 2 entries:
"B" => 2.0
"A" => 1.0
使用推导式来创建一个字典:
实例
Dict{String, Float64} with 19 entries:
"85" => 0.996195
"20" => 0.34202
...
访问字典
使用方括号加键来访问对应的值:
实例
julia> D["A"]
1
# 访问不存在的键会抛出 KeyError
julia> D["X"]
ERROR: KeyError: key "X" not found
如果想在不存在的键上返回默认值而不报错,使用 get() 函数;get!() 还会把默认值写回字典:
实例
0
julia> get(D, "A", 0) # 键存在返回实际值
1
julia> get!(D, "C", 3) # C 不存在,写入并返回默认值
3
添加与修改
字典中的键是唯一的,如果我们为一个已经存在的键分配一个值,不会创建新的键,而是修改现有键的值:
实例
3
julia> D["A"] = 100 # 修改已有键的值
100
julia> D
Dict{String, Int64} with 3 entries:
"B" => 2
"A" => 100
"C" => 3
删除键值对
我们可以使用 delete!() 函数删除已存在字典的键:
实例
Dict{String, Int64} with 2 entries:
"B" => 2
"A" => 100
pop!(D, key) 可以删除键值对并返回被删除的值。
查询键
我们可以使用 haskey() 函数来检查字典是否包含指定的 key:
实例
true
julia> haskey(D, "Z")
false
# in 检查的是完整的键值对
julia> in(("A" => 100), D)
true
julia> keys(D) # 获取所有键
KeySet for a Dict{String, Int64} with 2 entries. Keys:
"B"
"A"
查询值与遍历
我们可以使用 values() 查看字典所有值,并将字典作为可迭代对象来遍历键值对:
实例
ValueIterator for a Dict{String, Int64} with 2 entries. Values:
2
100
julia> for kv in D
println(kv)
end
"B" => 2
"A" => 100
# 也可以同时解构键和值
julia> for (k, v) in D
println("键 $k 的值是 $v")
end
键 B 的值是 2
键 A 的值是 100
合并字典
merge() 返回合并后的新字典,键冲突时后面的字典覆盖前面的值;merge!() 则原地合并到第一个字典:
实例
julia> d2 = Dict("b"=>3, "c"=>4);
julia> merge(d1, d2) # b 的值被 d2 覆盖
Dict{String, Int64} with 3 entries:
"a" => 1
"b" => 3
"c" => 4
# mergewith 可以自定义冲突时的合并规则
julia> mergewith(+)(d1, d2) # 冲突时相加
Dict{String, Int64} with 3 entries:
"a" => 1
"b" => 5
"c" => 4
字典排序
字典本身是无序的,但我们可以使用 sort() 函数对键排序后遍历:
实例
julia> for key in sort(collect(keys(runoob_dict)))
println("$key => $(runoob_dict[key])")
end
R => 100
S => 220
T => 350
U => 400
V => 575
W => 670
如果需要字典始终保持排序状态,可以使用 DataStructures 包中的 SortedDict 数据类型。
使用第三方包需要先安装它,在 REPL 中输入符号 ],进入 pkg 模式:
julia> ] # 输入 ] 就进入 pkg 模式
添加包的语法格式为 add 包名,以下我们添加 DataStructures 包:
(@v1.10) pkg> add DataStructures
未注册的包,可以直接指定 url:
pkg> add https://github.com/fredrikekre/ImportMacros.jl
本地包:
pkg> add 本地路径/包名.jl
实例
julia> runoob_dict = DataStructures.SortedDict("S" => 220, "T" => 350, "U" => 400, "V" => 575, "W" => 670)
DataStructures.SortedDict{String, Int64, Base.Order.ForwardOrdering} with 5 entries:
"S" => 220
"T" => 350
...
julia> runoob_dict["R"] = 100
100
julia> runoob_dict # 键始终保持有序
DataStructures.SortedDict{String, Int64, Base.Order.ForwardOrdering} with 6 entries:
"R" => 100
"S" => 220
...
Set(集合)
Julia Set(集合)是没有重复对象的数据集,所有的元素都是唯一的。
以下是 Set 和其他类型的集合之间的区别:
- Set 中的元素是唯一的
- Set 中元素的顺序不重要
创建 Set 集合
借助 Set 构造函数,我们可以创建如下集合:
实例
Set{Any}()
julia> num_primes = Set{Int64}()
Set{Int64}()
julia> var_site = Set{String}(["Google", "Runoob", "Taobao"])
Set{String} with 3 elements:
"Google"
"Taobao"
"Runoob"
我们可以使用 push!() 函数添加集合元素:
实例
Set{String} with 4 elements:
"Google"
"Wiki"
"Taobao"
"Runoob"
# 添加重复元素不会有任何效果
julia> push!(var_site, "Runoob")
Set{String} with 4 elements:
"Google"
"Wiki"
"Taobao"
"Runoob"
我们可以使用 in() 函数查看元素是否存在于集合中:
实例
true
julia> "Zhihu" in var_site # in 的中缀写法
false
集合运算
并集、交集和差集是我们可以对集合常用的一些操作,这些操作对应的函数是 union()、intersect() 和 setdiff():
实例
julia> B = Set(["red", "orange", "yellow", "green", "blue", "indigo", "violet"]);
并集:两个集合所有的元素合并在一起组成的集合:
实例
Set{String} with 8 elements:
"indigo"
"green"
"black"
"yellow"
...
交集:既属于 A 又属于 B 的元素组成的集合:
实例
Set{String} with 3 elements:
"blue"
"green"
"red"
差集:属于 A 但不属于 B 的元素:
实例
Set{String} with 1 element:
"black"
此外还有子集判断函数 issubset()(运算符 ⊆)和判断两个集合是否相等 issetequal():
实例
true
julia> issubset(Set([1, 2]), Set([1, 2, 3]))
true
julia> issetequal(Set([1, 2]), Set([2, 1])) # 与顺序无关
true
提示:union、intersect、setdiff 同样适用于数组,常用于快速去重:unique(A) 返回去除重复元素后的数组。
字典常用函数速查
| 函数 | 描述 |
|---|---|
D[k] | 取键 k 对应的值,不存在时抛 KeyError |
get(D, k, default) | 取值,键不存在时返回 default |
get!(D, k, default) | 取值,键不存在时写入 default 并返回 |
haskey(D, k) | 判断键是否存在 |
delete!(D, k) | 删除键值对 |
pop!(D, k) | 删除键值对并返回值 |
keys(D) / values(D) | 所有键 / 所有值 |
length(D) | 键值对个数 |
merge(D1, D2) | 合并字典,后者覆盖前者 |
