Julia 字典和集合

Julia 字典(Dict)与集合(Set)完全指南(中文版)

“高效、类型安全、无序存储” —— Julia 的哈希容器性能卓越


一、总览对比

特性Dict{K,V}Set{T}
存储键值对唯一元素
顺序无序无序
重复键唯一元素唯一
查找O(1) 平均O(1) 平均
内存稍高稍低
primordial键值映射去重、成员测试

二、字典 Dict —— 键值对存储

1. 创建字典

# 基本语法
d1 = Dict("a" => 1, "b" => 2, "c" => 3)

# 空字典(指定类型)
d2 = Dict{String, Int}()
d3 = Dict{String, Float64}("pi" => 3.14)

# 类型推断
d4 = Dict("x" => 1, "y" => 2.0)  # Dict{String, Float64}

2. 访问与修改

d = Dict("name" => "Julia", "version" => 1.10)

# 读取
d["name"]        # "Julia"
get(d, "name", "unknown")  # "Julia"
get(() -> "unknown", d, "name")  # 函数式默认值

# 修改
d["version"] = 1.11
d["year"] = 2012

# 删除
delete!(d, "year")
pop!(d, "version", nothing)  # 删除并返回

# 检查键
haskey(d, "name")    # true
"name" in keys(d)    # true

3. 遍历字典

for (k, v) in d
    println("$k => $v")
end

for k in keys(d)
    println(k)
end

for v in values(d)
    println(v)
end

4. 合并字典

d1 = Dict("a" => 1, "b" => 2)
d2 = Dict("b" => 20, "c" => 3)

merge(d1, d2)        # {"a"=>1, "b"=>20, "c"=>3}
merge!(d1, d2)       # 修改 d1

三、集合 Set —— 唯一元素集合

1. 创建集合

# 基本语法
s1 = Set([1, 2, 2, 3, 3, 4])   # Set{Int64} with 4 elements: {1,2,3,4}

# 空集合
s2 = Set{Int}()

# 类型推断
s3 = Set(["apple", "banana", "apple"])  # Set{String}

2. 添加与删除

s = Set([1, 2, 3])

push!(s, 4)      # {1,2,3,4}
push!(s, 4)      # 无变化(已存在)

delete!(s, 3)    # {1,2,4}
pop!(s)          # 移除并返回任意元素(如 1)

3. 成员测试

4 in s           # true
inset(4, s)      # 同上

4. 集合运算

A = Set([1, 2, 3, 4])
B = Set([3, 4, 5, 6])

union(A, B)      # 并集 {1,2,3,4,5,6}
intersect(A, B)  # 交集 {3,4}
setdiff(A, B)    # 差集 {1,2}
issubset(A, B)   # A ⊆ B ? false

符号写法:

A ∪ B, A ∩ B, A \ B

四、字典与集合的类型参数

# 明确指定类型(推荐用于性能)
d = Dict{String, Int}("count" => 100)

# 任意键值(不推荐)
d_any = Dict("a" => 1, 2 => "b")  # Dict{Any, Any}

性能提示:使用具体类型避免 Any,提升速度与内存效率


五、OrderedDict 与 OrderedSet(有序版本)

需安装:] add OrderedCollections

using OrderedCollections

od = OrderedDict("c" => 3, "a" => 1, "b" => 2)
# 保持插入顺序:c, a, b

os = OrderedSet([3, 1, 2])
# 保持插入顺序:3, 1, 2

六、性能对比(哈希 vs 数组)

using BenchmarkTools

arr = 1:1_000_000
dict = Dict(i => i for i in arr)
set = Set(arr)

@btime 500_000 in arr;      # ~100 μs
@btime haskey(dict, 500_000); # ~10 ns
@btime 500_000 in set;      # ~10 ns

结论:查找 O(1) vs O(n) → 字典/集合完胜!


七、综合示例:词频统计

function word_frequency(text::AbstractString)
    freq = Dict{String, Int}()
    for word in split(lowercase(text), r"\W+"; keepempty=false)
        freq[word] = get(freq, word, 0) + 1
    end
    return freq
end

text = "To be or not to be, that is the question."
word_frequency(text)
# Dict("to" => 2, "be" => 2, "or" => 1, ...)

八、综合示例:图的邻接表表示

# 无向图
graph = Dict{String, Set{String}}()

function add_edge!(g, a, b)
    get!(Set{String}, g, a) |> x -> push!(x, b)
    get!(Set{String}, g, b) |> x -> push!(x, a)
end

add_edge!(graph, "A", "B")
add_edge!(graph, "A", "C")
add_edge!(graph, "B", "D")

graph
# Dict("A" => Set(["B","C"]), "B" => Set(["A","D"]), ...)

九、字典与集合速查表

操作DictSet
创建Dict(k=>v, ...)Set([1,2,3])
添加d[k] = vpush!(s, x)
删除delete!(d, k)delete!(s, x)
查找haskey(d, k)x in s
获取get(d, k, def)
遍历keys(d), values(d)for x in s
合并merge(d1, d2)union(s1, s2)
交集intersect(s1, s2)
差集setdiff(s1, s2)

十、小练习(立即上手)

  1. 实现 invert_dict(d) 反转键值对(值唯一)
  2. 写函数 common_friends(graph, a, b) 返回共同好友集合
  3. 实现 group_by(arr, f) 按函数返回值分组(返回 Dict)
  4. 性能测试:用 Set 去重 100 万随机数 vs 数组
  5. 实现 DefaultDict(不存在的键返回默认值)

答案示例

# 1. 反转字典
invert_dict(d) = Dict(v => k for (k,v) in d)

# 2. 共同好友
function common_friends(graph, a, b)
    get(graph, a, Set()) ∩ get(graph, b, Set())
end

# 3. group_by
function group_by(arr, f)
    result = Dict{Any, Vector{eltype(arr)}}()
    for x in arr
        k = f(x)
        push!(get!(Vector{eltype(arr)}, result, k), x)
    end
    return result
end

group_by(1:10, iseven)
# Dict(false => [1,3,5,7,9], true => [2,4,6,8,10])

# 4. 去重性能
using Random
data = rand(1:100_000, 1_000_000)

@btime unique(data);           # ~50 ms
@btime Set(data);              # ~15 ms

# 5. DefaultDict
struct DefaultDict{K,V,F} <: AbstractDict{K,V}
    dict::Dict{K,V}
    default::F
end

DefaultDict(default) = DefaultDict(Dict(), default)

function Base.getindex(d::DefaultDict{K,V}, k) where {K,V}
    get!(d.dict, k) do
        d.default()
    end
end

十一、常见错误与避坑

错误正确做法
d["new_key"] 访问不存在的键get(d, k, def)haskey
Set([1, 2.0]) 混用类型集合元素类型统一
push!(d, k=>v)d[k] = v
字典键为可变对象(如 [1,2]不可变键(如 Tuple
# 正确:用元组做复合键
d = Dict()
d[(1, 2)] = "A"
d[(3, 4)] = "B"

十二、进阶:符号字典 Dict{Symbol, Any}

config = Dict(:debug => true, :port => 8000, :timeout => 30)
config[:debug] = false

常用于配置、参数传递


恭喜!你已精通 Julia 字典与集合!

现在你可以:

  • Dict 构建配置系统、缓存、图结构
  • Set 实现去重、成员测试、集合运算
  • 写出高性能数据处理管道
  • 设计优雅的 API 参数系统

下一站推荐

主题为什么学
NamedTuple轻量带名元组
struct自定义类型
DataFrames表格数据
JSON.jl序列化字典
Caching字典缓存

需要我:

  • 写一个 配置文件解析器(.json/.toml)?
  • 实现 LRU 缓存(用 Dict + OrderedDict)?
  • 构建 图算法库(DFS/BFS)?
  • 对比 Dict vs NamedTuple 性能

随时告诉我!

文章已创建 2302

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部