字典
除了内置的基本类型外,数组和字典也是内置类型。
map实现
从map的源代码定义看,map是通过2个struct实现的。
vlib/builtin/map.v
pub struct map {
// Number of bytes of a key
key_bytes int
// Number of bytes of a value
value_bytes int
mut:
// Highest even index in the hashtable
even_index u32
// Number of cached hashbits left for rehashing
cached_hashbits u8
// Used for right-shifting out used hashbits
shift u8
// Array storing key-values (ordered)
key_values DenseArray
// Pointer to meta-data:
// - Odd indices store kv_index.
// - Even indices store probe_count and hashbits.
metas &u32
// Extra metas that allows for no ranging when incrementing
// index in the hashmap
extra_metas u32
has_string_keys bool
hash_fn MapHashFn
key_eq_fn MapEqFn
clone_fn MapCloneFn
free_fn MapFreeFn
pub mut:
// Number of key-values currently in the hashmap
len int //字典的大小,也就是键值对的数量,这是map唯一可以对外直接访问的属性,只读
}
struct DenseArray {
key_bytes int
value_bytes int
mut:
cap int
len int
deletes u32 // count
// array allocated (with `cap` bytes) on first deletion
// has non-zero element when key deleted
all_deleted &u8 = unsafe { nil }
keys &u8 = unsafe { nil }
values &u8 = unsafe { nil }
}
map定义
fn main() {
mut m := map[string]int{} //字面量创建字典
m['one'] = 1 //如果key不存在,则是新增
m['one'] = 11 //如果key存在,则是修改
m['two'] = 2
println(m['one']) //返回对应的value
println(m['bad_key']) // 如果指定key不存在,返回该类型的默认值,0
}
map的key除了string类型,也可以是其他任何类型。
string类型的key:
map[string]int
map[string]User
map[string][]int
非string类型的key:
module main
enum Token {
aa = 2
bb
cc
}
fn main() {
//非字符串key
// int key 整数
mut m1 := map[int]int{}
m1[3] = 9
m1[4] = 16
println(m1)
// voidptr key 通用指针
mut m2 := map[voidptr]string{}
v := 5
m2[&v] = 'var'
m2[&m2] = 'map'
println(m2)
// rune key unicode码
mut m3 := {
`!`: 2 //是反引号`,不是单引号'
`%`: 3
}
println(typeof(m3).name) // map[rune]int
println(m3)
// u8 key 字节
mut m4 := map[u8]string{}
m4[u8(1)] = 'a'
m4[u8(2)] = 'b'
println(m4)
// float key 小数
mut m5 := map[f64]string{}
m5[1.2] = 'a'
m5[2.0] = 'b'
println(m5)
// enum key 枚举值
mut m6 := map[Token]string{}
m6[Token.aa] = 'abc'
m6[Token.bb] = 'def'
println(m6)
}
map字面量初始化,编译器会进行类型推断:
fn main() {
m := {
'one': 1
'two': 2
'three': 3
}
m2 := {
1: 'a'
2: 'b'
3: 'c'
}
println(m)
println(m2)
}
map.len返回字典的大小:
fn main() {
mut m := map[string]int{}
m['one'] = 1
m['two'] = 2
println(m.len) // 返回2
}
in操作符
判断某一个元素是否包含在map的key中:
fn main() {
mut m := map[string]int{}
m['one'] = 1
m['two'] = 2
println('one' in m) //返回true
println('three' in m) //返回false
}
遍历map
fn main() {
mut m := map[string]int{}
m['one'] = 1
m['two'] = 2
m['three'] = 3
for key, value in m {
println('key:$key,value:$value')
}
for key, _ in m {
println('key:$key')
}
for _, value in m {
println('value:$value')
}
}
访问字典成员错误处理
module main
fn main() {
sm := {
'abc': 'xyz'
}
val := sm['bad_key']
println(val) // 如果字典元素不存在,会返回该类型的默认值:空字符串
intm := {
1: 1234
2: 5678
}
s := intm[3]
println(s) // 如果字典元素不存在,会返回该类型的默认值:0
//也可以加上or代码块来进行错误处理
mut mm := map[string]int{}
mm['abc'] = 1
val2 := mm['bad_key'] or { panic('key not found') } //如果元素不存在,在or代码块中进行错误处理
val3 := mm['bad_key'] or { 100 } //如果元素不存在,也可以在or代码块中返回默认值,类型必须和字典的value类型一致
// println(val2)
println(val3)
if val4 := mm['abc'] { //如果元素存在,赋值成功,才执行
println(val4)
}
myfn() or { panic(err) }
}
fn myfn() ! {
mm := map[string]int{}
x := mm['bad_key']! //也可以本层级不处理,向上抛转错误
println(x)
}
if条件语句判断字典成员是否存在
fn main() {
mut m := {'xy': 5, 'zu': 7}
mut res := []int{cap:2}
for k in ['jk', 'zu'] {
if x := m[k] { //检查字典m[k]是否存在,如果存在,则赋值,if条件返回true,如果不存在,则返回false
res << x
} else {
res << -17
}
}
println(res) //[-17,7]
}
删除字典成员
fn main() {
mut m := map[string]int{} //字面量创建字典
m['one'] = 1 //如果key不存在,则是新增
m['one'] = 11 //如果key存在,则是修改
m['two'] = 2
println(m['two'])
m.delete('two') //删除字典成员
println(m['two']) //不存在返回默认值0
}
字典相关的源代码可以参考:vlib/builtin/map.v。
最后更新于