Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

使用 Set 存储唯一值

我们将在本章讨论的最后一个常用集合是 SetSet<T> 类型是唯一值的集合。与列表不同,Set 保证不包含重复元素。与 Map 一样,Set 是一个用于存储值的集合,但在 Set 中,每个值都是自己的键,并且没有关联的值。

当你想确保没有重复值时,Set 很有用。例如,你可以使用 Set 来跟踪访问过的网站、事件中的唯一访客,或单词在文档中出现的唯一单词。

创建新 Set

创建空 Set 的一种方法是使用 Set::new

let unique_numbers: Set<integer> = Set::new()

请注意,我们需要显式注解类型,因为我们还没有插入任何值。

另一种创建 Set 的方法是使用从列表或值序列创建 Set 的语法:

let unique_numbers = Set::from([1, 2, 3, 4, 5])

或者使用花括号语法:

let unique_numbers = { 1, 2, 3, 4, 5 }

这两种方法都会创建一个包含五个唯一整数的 Set。

Set 自动处理重复项

Set 最有用的特性之一是它们会自动删除重复项。让我们看看这是如何工作的:

let numbers = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
let unique_numbers = Set::from(numbers)

此时,unique_numbers 将只包含 {1, 2, 3, 4}。所有重复项都已自动删除。

读取 Set 的值

我们可以检查 Set 中是否存在某个值,使用 contains 方法:

let numbers = { 1, 2, 3, 4, 5 }
println("有 3 吗? ", numbers.contains(3))  // true
println("有 6 吗? ", numbers.contains(6))  // false

我们也可以像遍历列表元素那样使用 for 循环遍历 Set 中的每个元素:

let numbers = { 1, 2, 3, 4, 5 }
for number in numbers {
  println(number)
}

这将以任意顺序打印每个数字。

更新 Set

与其他集合一样,Set 通常是不可变的,但我们可以创建包含新元素的新 Set。

添加元素

我们可以使用 Set::insert 方法向 Set 添加元素:

let numbers = { 1, 2, 3 }
let numbers2 = Set::insert(numbers, 4)
let numbers3 = Set::insert(numbers2, 4)  // 不会改变 Set,因为 4 已经存在

Set::insert 返回一个新 Set,如果元素已存在,则新 Set 与原始 Set 相同。

删除元素

我们可以使用 Set::remove 方法从 Set 中删除元素:

let numbers = { 1, 2, 3, 4, 5 }
let numbers2 = Set::remove(numbers, 3)

此时,numbers2 将包含 {1, 2, 4, 5}

集合操作

Set 对集合操作有很好的支持,例如并集、交集、差集和对称差集。让我们看看这些如何工作。

并集

两个 Set 的并集是一个包含任一 Set 中所有元素的新 Set:

let a = { 1, 2, 3, 4 }
let b = { 3, 4, 5, 6 }
let union = Set::union(a, b)  // {1, 2, 3, 4, 5, 6}

交集

两个 Set 的交集是一个包含同时出现在两个 Set 中的所有元素的新 Set:

let a = { 1, 2, 3, 4 }
let b = { 3, 4, 5, 6 }
let intersection = Set::intersection(a, b)  // {3, 4}

差集

两个 Set 的差集是一个包含第一个 Set 中但不在第二个 Set 中的所有元素的新 Set:

let a = { 1, 2, 3, 4 }
let b = { 3, 4, 5, 6 }
let difference = Set::difference(a, b)  // {1, 2}

对称差集

两个 Set 的对称差集是一个包含任一 Set 中但不同时在两个 Set 中的所有元素的新 Set:

let a = { 1, 2, 3, 4 }
let b = { 3, 4, 5, 6 }
let symmetric_difference = Set::symmetric_difference(a, b)  // {1, 2, 5, 6}

常见的 Set 操作

Set 类型有许多有用的方法。让我们看看其中一些。

获取 Set 大小

我们可以使用 len 方法获取 Set 中的元素数:

let numbers = { 1, 2, 3, 4, 5 }
println("Set 大小: ", numbers.len())  // 打印 5

检查 Set 是否为空

我们可以使用 is_empty 方法检查 Set 是否为空:

let empty_set: Set<integer> = {}
println("Set 为空: ", empty_set.is_empty())  // true

子集和超集

我们可以检查一个 Set 是否是另一个 Set 的子集(包含在其中)或超集(包含另一个):

let a = { 1, 2, 3 }
let b = { 1, 2, 3, 4, 5 }

println("a 是 b 的子集吗? ", Set::is_subset(a, b))  // true
println("b 是 a 的超集吗? ", Set::is_superset(b, a))  // true

转换为列表

我们可以使用 to_list 方法将 Set 转换为列表:

let numbers = { 1, 2, 3, 4, 5 }
let number_list = Set::to_list(numbers)  // [1, 2, 3, 4, 5] 或其他顺序

Set 实际应用示例

让我们看一个 Set 在实际中有用的示例。假设我们正在构建一个网站跟踪器,想要跟踪访问过我们网站的唯一用户:

type Visitor = {
  id: String,
  name: String
}

// 创建一些访问者
let alice = { id: String::from("1"), name: String::from("Alice") }
let bob = { id: String::from("2"), name: String::from("Bob") }
let charlie = { id: String::from("3"), name: String::from("Charlie") }

// 跟踪唯一访问者
let mutable unique_visitors = { alice, bob }

// Alice 再次访问 - 不会添加重复项
unique_visitors = Set::insert(unique_visitors, alice)

// Charlie 第一次访问
unique_visitors = Set::insert(unique_visitors, charlie)

println("唯一访问者数量: ", unique_visitors.len())  // 3

在这个示例中,即使 Alice 访问了两次,她在 Set 中也只被计算一次。

总结

Set 是 X 语言标准库中一个强大的集合类型。它们:

  • 自动处理重复值
  • 支持快速查找操作
  • 提供标准集合操作,如并集、交集和差集
  • 对于跟踪唯一值或执行集合数学运算非常有用

列表、Map 和 Set 共同为你提供了在 X 语言中管理数据集合所需的大多数工具。

现在我们已经介绍了 X 语言中的常见集合,让我们继续讨论 X 语言处理错误的方式!