236 lines
8.6 KiB
Markdown
236 lines
8.6 KiB
Markdown
# TSL 数组、键表、矩阵样数据与集合运算
|
|
|
|
文档类型:语法主线
|
|
是否可直接用于生成代码:是
|
|
是否含可直接照写示例:是
|
|
是否含不可照写反例:否
|
|
遇到不确定时:先按本页候选页继续判断;[13_resultset_and_filters.md](13_resultset_and_filters.md)、[22_matrix_deep_dive.md](22_matrix_deep_dive.md)、[23_fmarray.md](23_fmarray.md)、[14_ts_sql.md](14_ts_sql.md);仍不命中时回到语法路由中心 [index.md](index.md);如果问题已经超出语法层,回到 TSL 总入口 [../index.md](../index.md)
|
|
|
|
这一篇收拢 `array(...)` 的扩展用法:顺序数组、字符串键表、嵌套数组、本页明确的矩阵样比较,以及 `in` / `sqlin` / `union2` / `intersect` / `minus` / `outersect` 这类去重型集合关系。
|
|
|
|
## 本篇职责
|
|
|
|
回答“`array(...)` 在 TSL 里除了最普通的一维数组,还能怎样组织数据;哪些矩阵样写法属于本页文档明确形态;元素、子集、整行和行集合关系应该怎样判断”。
|
|
|
|
## 智能体数组/矩阵样数据判断流程
|
|
|
|
1. 先判断需要顺序数组、字符串键表、嵌套数组、矩阵样比较,还是去重型集合关系。
|
|
2. 普通容器优先从 `array(...)` 起手;下标和键访问回看值语法页。
|
|
3. 矩阵链式比较只照 `::` 系列文档明确示例写,不要混用标量链式比较。
|
|
4. 基础成员判断用 `in` / `not in`;整行存在判断用 `sqlin` / `not sqlin`;去重型行集合并、交、差、对称差用 `union2` / `intersect` / `minus` / `outersect`。
|
|
5. 结果集过滤或 TS-SQL 查询需求分别跳转到 [13_resultset_and_filters.md](13_resultset_and_filters.md) 或 [14_ts_sql.md](14_ts_sql.md)。
|
|
6. 没有对应代码块时不要发明数组/矩阵样数据/集合关系写法。
|
|
|
|
## 核心规则
|
|
|
|
- `array(...)` 既可以写顺序数组,也可以写字符串键表。
|
|
- 顺序数组下标从 `0` 开始;字符串仍然从 `1` 开始。
|
|
- `array(...)` 可以继续嵌套,形成二维或矩阵样数据。
|
|
- 矩阵链式比较 `::>`、`::<`、`::<>`、`::==`、`::>=`、`::<=` 属于本页文档明确形态。
|
|
- `in` / `not in` 处理的是元素存在关系,以及左侧为数组时的子集关系。
|
|
- `sqlin` / `not sqlin` 处理的是行存在关系;左侧要当成一整行去匹配右侧结果集。
|
|
- `union2`、`intersect`、`minus`、`outersect` 都按“行”运算,而不是按单元格逐个运算。
|
|
- 集合运算结果会折叠重复行;如果需求是保留重复记录,改看 [13_resultset_and_filters.md](13_resultset_and_filters.md)。
|
|
- 当数据本身就是一维数组时,按行集合运算和按元素集合运算是一致的。
|
|
- 左侧是数组时,先判定需求语义:子集关系用 `in`,整行存在关系用 `sqlin`。
|
|
|
|
## 可直接照写示例
|
|
|
|
### 基础数组与键表
|
|
|
|
顺序数组与字符串键表:
|
|
|
|
代码块身份:可直接照写示例
|
|
|
|
```tsl
|
|
arr := array(10, 20, 30);
|
|
hash := array("Code": "0001", "Price": 12.3);
|
|
writeLn("ARR0=", arr[0]);
|
|
writeLn("ARR1=", arr[1]);
|
|
writeLn("HASH=", hash["Code"]);
|
|
```
|
|
|
|
结果说明:
|
|
|
|
- `arr[0] = 10`
|
|
- `arr[1] = 20`
|
|
- `hash["Code"] = "0001"`
|
|
|
|
嵌套数组:
|
|
|
|
代码块身份:可直接照写示例
|
|
|
|
```tsl
|
|
[r1, r2] := array((1, 2), (3, 4));
|
|
writeLn(r1[0]);
|
|
writeLn(r1[1]);
|
|
writeLn(r2[0]);
|
|
writeLn(r2[1]);
|
|
```
|
|
|
|
结果说明:
|
|
|
|
- 依次输出 `1`、`2`、`3`、`4`
|
|
- 说明 `array((1, 2), (3, 4))` 这种嵌套数组写法可以按普通数组继续读取
|
|
|
|
代码块身份:输出片段
|
|
|
|
```text
|
|
1
|
|
2
|
|
3
|
|
4
|
|
```
|
|
|
|
### 矩阵样比较
|
|
|
|
矩阵链式比较:
|
|
|
|
代码块身份:可直接照写示例
|
|
|
|
```tsl
|
|
r := array(1, 2, -1) ::< array(2, 1, 0) ::< array(3, 2, 1);
|
|
writeLn(r[0]);
|
|
writeLn(r[1]);
|
|
writeLn(r[2]);
|
|
s := array(1, 2, -1) ::< 2 ::< array(3, 2, 1);
|
|
writeLn(s[0]);
|
|
writeLn(s[1]);
|
|
writeLn(s[2]);
|
|
```
|
|
|
|
结果说明:
|
|
|
|
- `array(1, 2, -1) ::< array(2, 1, 0) ::< array(3, 2, 1)` 的三个元素依次输出 `1`、`0`、`1`
|
|
- `array(1, 2, -1) ::< 2 ::< array(3, 2, 1)` 的三个元素依次输出 `1`、`0`、`0`
|
|
- 说明矩阵链式比较会按元素位置分别得到结果数组,并且可以和标量混用
|
|
|
|
### `in`、`not in`、`sqlin`、`not sqlin`
|
|
|
|
`in` 既可以判断单个元素是否存在,也可以判断左侧数组是否是右侧结果集的子集:
|
|
|
|
代码块身份:可直接照写示例
|
|
|
|
```tsl
|
|
writeLn(1 in array(1, 2, 2));
|
|
writeLn(1 in array(0, 2));
|
|
writeLn(1 in array((1), (2)));
|
|
writeLn(array(1, 2) in array(1, 2, 3, 4));
|
|
writeLn(array(1, 3) in array((1, 2), (3, 4)));
|
|
writeLn(array(1, 2) in array(1));
|
|
writeLn(1 not in array(0, 2));
|
|
```
|
|
|
|
结果说明:
|
|
|
|
- `1 in array(1, 2, 2)` 输出 `1`
|
|
- `1 in array(0, 2)` 输出 `0`
|
|
- `1 in array((1), (2))` 输出 `1`
|
|
- `array(1, 2) in array(1, 2, 3, 4)` 输出 `1`
|
|
- `array(1, 3) in array((1, 2), (3, 4))` 输出 `1`
|
|
- `array(1, 2) in array(1)` 输出 `0`
|
|
- `1 not in array(0, 2)` 输出 `1`
|
|
|
|
代码块身份:输出片段
|
|
|
|
```text
|
|
1
|
|
0
|
|
1
|
|
1
|
|
```
|
|
|
|
`sqlin` 按整行判断左侧是否存在于右侧结果集中:
|
|
|
|
代码块身份:可直接照写示例
|
|
|
|
```tsl
|
|
writeLn(1 sqlin array(1, 2));
|
|
writeLn(array(1, 2) sqlin array(1, 2, 3));
|
|
writeLn(array(1, 2) sqlin array((1, 2), (3, 4)));
|
|
writeLn(array(5, 6) not sqlin array((1, 2), (3, 4)));
|
|
```
|
|
|
|
结果说明:
|
|
|
|
- `1 sqlin array(1, 2)` 输出 `1`
|
|
- `array(1, 2) sqlin array(1, 2, 3)` 输出 `0`
|
|
- `array(1, 2) sqlin array((1, 2), (3, 4))` 输出 `1`
|
|
- `array(5, 6) not sqlin array((1, 2), (3, 4))` 输出 `1`
|
|
- `in` 看元素或子集
|
|
- `sqlin` 看整行
|
|
|
|
### 行集合并、交、差、对称差
|
|
|
|
下面这组最小例子展示“按行运算”和“结果会折叠重复行”:
|
|
|
|
代码块身份:可直接照写示例
|
|
|
|
```tsl
|
|
left_rows := array((1, 2), (1, 2), (2, 3));
|
|
right_rows := array((1, 2), (3, 4));
|
|
union_rows := left_rows union2 right_rows;
|
|
intersect_rows := left_rows intersect right_rows;
|
|
minus_rows := left_rows minus right_rows;
|
|
outersect_rows := left_rows outersect right_rows;
|
|
```
|
|
|
|
结果说明:
|
|
|
|
- `left_rows union2 right_rows` 共有三行:`(1,2)`、`(2,3)`、`(3,4)`
|
|
- `left_rows intersect right_rows` 只有一行:`(1,2)`
|
|
- `left_rows minus right_rows` 只有一行:`(2,3)`
|
|
- `left_rows outersect right_rows` 有两行:`(2,3)`、`(3,4)`
|
|
- `left_rows` 原本有两行相同的 `(1,2)`,但 `union2` / `intersect` 的结果都只保留一份,说明集合运算会折叠重复行
|
|
|
|
更大的四列结果集文档结果:
|
|
|
|
- `array((1,2,3,4),(2,3,4,5),(1,1,1,1)) union2 array((1,2,3,4),(3,4,5,6),(2,2,2,2))`
|
|
返回 `array((1,2,3,4),(2,3,4,5),(1,1,1,1),(3,4,5,6),(2,2,2,2))`
|
|
- 同一组输入下:
|
|
`intersect` 返回 `array((1,2,3,4))`
|
|
- 同一组输入下:
|
|
`minus` 返回 `array((2,3,4,5),(1,1,1,1))`
|
|
- 同一组输入下:
|
|
`outersect` 返回 `array((2,3,4,5),(1,1,1,1),(3,4,5,6),(2,2,2,2))`
|
|
|
|
## 和过滤运算的区别
|
|
|
|
- 集合运算先把数据当成“行集合”来看,再做包含、并交差。
|
|
- 过滤运算先保留“原结果集里的每一条命中记录”;因此重复行会保留下来。
|
|
- 需要“集合关系”时留在本页。
|
|
- 需要“从原表里筛出哪些行”时看 [13_resultset_and_filters.md](13_resultset_and_filters.md)。
|
|
|
|
## 默认生成模板
|
|
|
|
按需求语义从下面两种模板中选择:
|
|
|
|
代码块身份:可直接照写示例
|
|
|
|
```tsl
|
|
matched := 1 in array(1, 2, 3);
|
|
row_matched := array(1, 2) sqlin array((1, 2), (3, 4));
|
|
```
|
|
|
|
## 本页不生成的范围
|
|
|
|
- 专门的结果集过滤函数
|
|
- TS-SQL 查询与写回
|
|
- 更大范围的矩阵函数族
|
|
|
|
这些内容分别进入 [13_resultset_and_filters.md](13_resultset_and_filters.md)、[14_ts_sql.md](14_ts_sql.md)、[22_matrix_deep_dive.md](22_matrix_deep_dive.md) 或 [23_fmarray.md](23_fmarray.md),不再外跳到原目录。
|
|
|
|
## 禁止项
|
|
|
|
- 不要把字符串下标按数组的 `0` 起始规则来写;字符串索引回看 [03_values_and_literals.md](03_values_and_literals.md)。
|
|
- 不要把矩阵链式比较 `::...` 和标量链式比较混写成同一种语法。
|
|
- 不要把 `in` 和 `sqlin` 当成同一个概念。
|
|
- 不要期待 `union2` 保留重复行。
|
|
- 不要用集合运算去做“保留原始重复记录”的过滤任务。
|
|
- 不要把二维结果集默认当成“按元素逐个比较”的集合运算。
|
|
- 左侧数组要表达“这些值是否都属于右侧集合”时,用 `in`。
|
|
- 左侧数组要表达“这一整行是否存在于右侧结果集”时,用 `sqlin`。
|
|
- `minus` 表达集合差集;如果任务要求保留左侧原始重复次数,改走 [13_resultset_and_filters.md](13_resultset_and_filters.md) 的过滤规则。
|
|
- 不要在本页发明结果集过滤、TS-SQL 查询、写回语法或更大矩阵函数族。
|
|
- 不要把普通 `array(...)` 自动升级成 `FMArray`;只有任务明确命中时才进入 [23_fmarray.md](23_fmarray.md)。
|