有序集合间的对位运算
【摘要】
两个有序集合之间可能进行一一对应的计算,比如两个集合如何比较大小,怎样判断集合是否相等?如何简便快捷的处理集合间的对位运算,这里为你全程解析,并提供 esProc 示例代码。有序集合间的对位运算
有序集合间的对位运算,包括比较运算(>,<, 等于)和四则运算(+,-,*,/,%,\)。本问中讨论的集合,都是有序集合,有序集合的成员是有次序的。有序集合间的对位运算,会按照顺序使用对位成员进行比较或者四则运算。
1. 比较两个集合的大小
集合可以使用符号 ">" 或 "<" 比较大小,从第一个成员开始按照顺序比较对位成员。例如 [1,3,1] 与[1,2,2]比较大小时,首先比较各自的第一个成员,1 与 1 相等;继续比较各自的第二个成员,因为 3>2,所以 [1,3,1] 大于[1,2,2],无需比较后面的成员了。
【例 1】 以奥运会奖牌榜为例,查询哪几届奥运会中国奖牌榜排名比俄罗斯靠前。部分数据如下:
Game |
Nation |
Medal |
Game |
30 |
USA |
46,29,29 |
30 |
30 |
China |
38,27,23 |
30 |
30 |
UK |
29,17,19 |
30 |
30 |
Russia |
24,26,32 |
30 |
30 |
Korea |
13,8,7 |
30 |
… |
… |
… |
… |
奥运奖牌榜的规则是:首先对比金牌数量,金牌数高的排名靠前,金牌数低的排名靠后,金牌数相同的将会按照银牌数再次对比排名。银牌数高的排名靠前,银牌数低的排名靠后,银牌数相同的将会按照铜牌数再次对比排名。以此类推,铜牌数也相同的国家排名并列。
【SPL 脚本】
A |
B |
|
1 |
=file("Olympic.csv").import@cqt() |
/导入奥运会历届排名 |
2 |
=A1.run(Medal=Medal.split@c()) |
/奖牌字段按逗号拆分为奖牌数集合 |
3 |
=A2.group(Game) |
/按每届分组 |
4 |
=A3.select(~.select(Nation=="China").Medal>~.select(Nation=="Russia").Medal) |
/用 ">" 符号比较中俄的奖牌数集合大小,会按顺序依次比较金牌、银牌和铜牌数量,并选出中国排名更高的届。 |
5 |
=A4.(Game) |
/列出共有哪几届 |
A5的执行结果如下:
Game |
23 |
25 |
28 |
29 |
30 |
2. 比较两个集合是否相等
比较两个集合是否相等是很常见的需求,比如比较文件内容是否相同,比较数据表的数值是否发生变化等。例如比较集合 [1,2,3] 和[2,1,3]是否相等。通常来说,集合的的对位成员不完全一致,认为两个集合是不相等的。但是也有时候并不在意集合的成员顺序,只需要比较两个集合是否包含了同样的成员。
【例 2】 下面是随机抽样后生成的文件,比较两次随机抽样是否选出了相同的序号。部分数据如下:
ID |
Predicted_Y |
Original_Y |
10 |
0.012388464367608093 |
0.0 |
11 |
0.01519899123978988 |
0.0 |
13 |
0.0007920238885061248 |
0.0 |
19 |
0.0012656367468159102 |
0.0 |
21 |
0.009460545997473379 |
0.0 |
23 |
0.024176791871681664 |
0.0 |
… |
… |
… |
【SPL 脚本】
A |
B |
|
1 |
=file("p_old.csv").import@ct() |
/读取第一次输出的文件 |
2 |
=file("p_new.csv").import@ct() |
/读取第二次输出的文件 |
3 |
=cmp(A1.(ID),A2.(ID)) |
/使用函数 cmp() 比较两次生成的 ID 是否完全相同(成员值相等且顺序一致) |
A3的执行结果如下:
Member |
0 |
结果为 0 表示两个文件 ID 完全一致。
如果 ID 的顺序可能不同,可以使用函数 eq() 比较两个集合的成员是否相同:
A |
B |
|
3 |
=A1.(ID).eq(A2.(ID)) |
/使用函数 eq() 比较两次生成的 ID 值是否相同,不要求顺序一致。 |
3. 集合成员的对位计算
集合成员的对位计算,支持 +,-,*,/,%,\ 等四则运算。例如 3 天内 A 商店的销售额集合是 [2,3,4],B 商店的销售额集合是 [3,1,3],我们希望得到两个商店的销售额之和的集合 [5,4,7]。
【例 3】 求 2019 年 12 月 24 日到 26 日深证 300 (399007) 对深证成指 (399001) 的每日相对收益率。部分数据如下:
Date |
Code |
Name |
Open |
Close |
Amount |
2020/2/18 |
399001 |
Shenzhen |
11244.7651 |
11306.4863 |
3.19E+11 |
2020/2/17 |
399001 |
Shenzhen |
10974.9328 |
11241.4993 |
3.12E+11 |
2020/2/14 |
399001 |
Shenzhen |
10854.4551 |
10916.3117 |
2.77E+11 |
2020/2/13 |
399001 |
Shenzhen |
10936.5011 |
10864.3222 |
2.87E+11 |
2020/2/12 |
399001 |
Shenzhen |
10735.0475 |
10940.7952 |
2.66E+11 |
… |
… |
… |
… |
… |
… |
【SPL脚本】
A |
B |
|
1 |
=connect("db") |
/连接数据源 |
2 |
=["399007","399001"].(A1.query("select * from StockIndex where code=? and date between'2019-12-23'and '2019-12-26'",~)) |
/读取深证 300 和深证成指在 2019 年 12 月 23 日到 26 日的数据,取 23 日是为了计算涨幅 |
3 |
=A2.(~.calc(to(2,4),Close/Close[-1])) |
/分别计算 24 到 26 日每天的涨幅 |
4 |
=A3(1)--A3(2) |
/使用符号 "--" 将两个集合对位相减,即是相对收益率。符号??(?∈{+,-,*,/,%,\})用于两个集合中成员的对位计算。 |
A4的执行结果如下:
Member |
0.0031349096521252617 |
0.0011897141619391371 |
-4.4910504685946595E-4 |
《SPL CookBook》中还有更多相关计算示例。
英文版