集合类型
集合类型是数学概念集合的模型。集合的基础类型只能是具有一定大小的序数类型,即:
- int8-int16
- uint8/byte-uint16
- char
- enum
- 序数子区间类型,即 range[-10..10] 或等效类型。
当使用带符号的整数文字构造集合时,该集合的基础类型被定义为区间 0 .. DefaultSetElements-1 ,其中 DefaultSetElements 目前始终为 2^8。 集合基础类型的最大区间长度为 MaxSetElements ,目前始终为 2^16。具有更大区间长度的类型将被强制转换为区间 0 .. MaxSetElements-1 。
原因是集合被实现为高性能的bit vector。 试图用太大类型来声明集合将导致一个错误:
var s: set[int64] # 错误:集合太大;对于具有超过 2^16 个元素的序数类型,请使用 `std/sets`
注意: Nim 还提供了 hash sets (你需要通过 import std/sets 导入它们),它们没有这样的限制。
集合可以通过集合构造器来构造: {} 是空集。空集的类型与任何具体的集合类型兼容。 构造器也可以用来包含元素(和元素范围)。
type
CharSet = set[char]
var
x: CharSet
x = {'a'..'z', '0'..'9'} # 这构建了一个包含从'a' 到 'z' 的字母和从 '0' 到 '9' 的数字的集合。
`std/setutils` 模块提供了一种从可迭代对象初始化集合的方法:
import std/setutils
let uniqueChars = myString.toSet
集合支持以下操作。
运算 | 含义 |
---|---|
A + B | 两个集合的并集 |
A * B | 两个集合的交集 |
A - B | 两个集合的差集(A不包含B的元素) |
A == B | 集合相等 |
A <= B | 子集关系(A是B的子集或等于B) |
A < B | 严格子集关系(A是B的真子集) |
e in A | 集合成员关系(A包含元素e) |
e notin A | A不包含元素e |
contains(A, e) | A包含元素e |
card(A) | A的基数(A中元素的数量) |
incl(A, elem) | 相同于 A = A + {elem} |
excl(A, elem) | 相同于 A = A - {elem} |
位域
集合经常被用来为过程的 标记 定义类型。 这是比定义整数常量更利落的解决方案(而且类型安全),因为整数常量必须被 or “或”在一起。
enum、set和cast可以像下面这样一起使用:
type
MyFlag* {.size: sizeof(cint).} = enum
A
B
C
D
MyFlags = set[MyFlag]
proc toNum(f: MyFlags): int = cast[cint](f)
proc toFlags(v: int): MyFlags = cast[MyFlags](v)
assert toNum({}) == 0
assert toNum({A}) == 1
assert toNum({D}) == 8
assert toNum({A, C}) == 5
assert toFlags(0) == {}
assert toFlags(7) == {A, B, C}
要注意set是怎样将枚举值转换为2的幂值。
如果在C中使用枚举和集合,请使用distinct cint。
关于与 C 语言的互操作性,参阅bitsize 编译指示。
当前内容版权归 vectorworkshopbaoerjie 或其关联方所有,如需对内容或内容相关联开源项目进行关注与资助,请访问 vectorworkshopbaoerjie .