集合

集合

> LeekScript

集合set)是一种存放唯一值的容器。与其把它当成数组,不如把它想象成一个装着互不相同的值的袋子:我们不会问它“第 3 个元素是什么?”,而是问“某个值在不在里面?”。

它由两条性质定义:

这正是它和数组(Array)的区别:数组允许重复值,而且通过索引来操作。

---

什么时候该用集合,而不是数组?

只要问自己一个问题:“我是不是需要快速知道某个值在不在里面,或者需要避免重复?”

这个恒定的开销就是决定性的理由:在数组里判断一个值是否存在,必须把整个数组遍历一遍,里面有多少个元素就要消耗多少次操作。战斗中操作数是有限的,只要你会频繁地判断某个值在不在里面,集合就能带来天壤之别。

典型用法:记下已经走过的格子、保存已经发现的敌人而不怕重复记录,或者比较地形上的两块区域。

---

创建集合

可以用尖括号 `` 把集合的内容原原本本写出来,不过实际写 AI 时,往往是先建一个空集合,再在程序运行过程中把它填满。

.. 运算符可以生成一段连续的值,不必逐个列举:

也可以用 new Set() 创建集合,或者把一个数组、一个区间转换成集合:

集合不接受重复值,因此重复的元素在创建时就消失了。而插入顺序会被保留:

类型

集合可以按照内容带上类型:

| 类型 | 内容 | |-----------------|----------------------------| | Set | 只包含整数 | | Set | 只包含实数 | | Set | 任意类型的值 |

类型参数可以是任何类型:SetSetSet……

---

填充和清空集合

setPut(set, element)布尔值 用于添加一个值。它的返回值往往比添加本身更有用:如果该元素是新的就返回 true,如果已经存在则返回 false。用来判断“是不是第一次遇到”再合适不过。

setRemove(set, element)布尔值 移除一个值,如果该值原本存在就返回 true,否则返回 false —— 只在元素确实存在时才动手,很方便。

setClear(set)集合 会把集合彻底清空,比如下一回合还要接着用它的时候。

---

查询集合

集合真正的价值就体现在这里。

想知道某个值在不在集合里,最简短的写法是 in 运算符:element in set 返回一个布尔值。如果你更喜欢函数写法,setContains(set, element) 做的事完全一样,开销也一样。

setSize(set)整数 返回元素的个数,setIsEmpty(set)布尔值 表示集合是否为空(比写 setSize(s) == 0 更易读)。

---

组合与筛选集合

集合让你可以把一值当作整体来推理。下面这些函数接受两个集合,返回一个新的集合(或一个布尔值),不会改动原来的两个集合。这通常比自己手写循环简单得多。

setFilter(set, callback)集合 则是构造一个新的集合,只保留让回调函数返回 true 的元素:

---

遍历和转换

遍历集合要用 for ... in 循环。从 2.48 版本起,元素按插入顺序遍历,每次运行的顺序都相同。

如果你需要别的顺序,先用 setToArray(set)数组 把集合转换成数组,再对这个数组排序。

---

完整示例

---

速查表

| 写法 | 返回值 | 作用 | |----------------------------|-----------|-----------------------------------------------| | x in s | 布尔值 | x 是否存在 —— 只消耗 1 次操作 | | setContains(s, x) | 布尔值 | x 是否存在(开销与 in 相同) | | setPut(s, x) | 布尔值 | 添加 x;如果是新元素则为 true | | setRemove(s, x) | 布尔值 | 移除 x;如果原本存在则为 true | | setClear(s) | 集合 | 清空集合 | | setSize(s) | 整数 | 元素个数 | | setIsEmpty(s) | 布尔值 | 集合为空时为 true | | setToArray(s) | 数组 | 转换成数组(插入顺序) | | arrayToSet(t) | 集合 | 把数组转换成集合 | | intervalToSet(i) | 集合 | 把区间转换成集合 | | setFilter(s, f) | 集合 | 保留通过回调函数检验的元素 | | setUnion(s1, s2) | 集合 | A ∪ B | | setIntersection(s1, s2) | 集合 | A ∩ B | | setDifference(s1, s2) | 集合 | A \ B | | setDisjunction(s1, s2) | 集合 | 对称差 A △ B | | setIsSubsetOf(s1, s2) | 布尔值 | 如果 A ⊆ B 则为 true |