二分法查找时参数的写法

spl 提供了内存二分法查找,主要函数是 select@b(),还有针对主键的查找 find@b(),以及对有序文本文件的外存二分法查找,file(btx,csv,txt).iselect()。

select@b() 可以对序表、排列,数列、日期序列和文本序列进行二分法查找,只要保证对象升序排列。比如以下代码格中,A1 是一个只有 3 列的序表,一列文本,一列数字,一列日期,且 3 个列都是升序。如下所示:

A B
1 =26.new(char(~+64):key,~:val,date(2023,02,01)+~:dt)
2 序表查找文本字段 文本序列
3 =A1.select@b(key=="F") =A1.(key).select@b(~=="F")
4 =A1.select@b(key:"F") =A1.(key).select@b(~:"F")
5 =A1.select@b(key>"F") =A1.(key).select@b(~>"F")
6 =A1.select@b(key<="F") =A1.(key).select@b(~<="F")
7 =A1.select@b(key>"F"&&key<="H") =A1.(key).select@b(~>"F"&&~<="H")
8 =A1.select@b(key<="F"||key>"H") =A1.(key).select@b(~<="F"||~>"H")
9 =A1.select@b(between@b(key,"F":"H")) =A1.(key).select@b(between@b(~,"F":"H"))
10 序表查找数字字段 数字序列
11 =A1.select@b(val:6) =A1.(val).select@b(~:6)
12 =A1.select@b(val-6) =A1.(val).select@b(~-6)
13 =A1.select@b(val==6) =A1.(val).select@b(~==6)
14 =A1.select@b(val>6) =A1.(val).select@b(~>6)
15 =A1.select@b(val<=10) =A1.(val).select@b(~<=10)
16 =A1.select@b(val>=6&&val<=10) =A1.(val).select@b(~>=6&&~<=10)
17 =A1.select@b(val<6||val>=10) =A1.(val).select@b(~<6||~>=10)
18 =A1.select@b(between@b(val,6:10)) =A1.(val).select@b(between@b(~,6:10))
19 序表查找日期字段 日期序列
20 =A1.select@b(dt:date(202302,10)) =A1.(dt).select@b(~:date(202302,10))
21 =A1.select@b(dt-date(202302,10)) =A1.(dt).select@b(~-date(202302,10))
22 =A1.select@b(dt==date(202302,10)) =A1.(dt).select@b(~==date(202302,10))
23 =A1.select@b(dt>date(202302,10)) =A1.(dt).select@b(~>date(202302,10))
24 =A1.select@b(dt<=date(202302,10)) =A1.(dt).select@b(~<=date(202302,10))
25 =A1.select@b(dt>date(202302,10)&&dt =A1.(dt).select@b(~>date(202302,10)&&~
26 =A1.select@b(dt<=date(202302,10)||dt>=date(202302,16)) =A1.(dt).select@b(~<=date(202302,10)||~>=date(202302,16))
27 =A1.select@b(between@b(dt,date(202302,10):date(202302,16))) =A1.(dt).select@b(between@b(~,date(202302,10):date(202302,16)))
28 序表查找多字段组合复杂表达式
29 =A1.select@b(key>="F"&&val<=15&&(dt=date(202302,15)))

可以看到,针对序表、文本序列、数列和日期序列,参数中除了可以使用冒号和减号 :、- ,还可以使用常规的逻辑表达式 ==、>=、<=、&&、||,也可以使用 between@b(),甚至像代码格 A29 中针对序表的多字段组合的复杂表达式也可实现二分查找,很方便也很好用。

我的第一个问题是如何对序列的序列 (嵌套二层序列) 进行二分法查找? 使用时发现,对序列的序列使用二分法时,参数的写法上会有一些限制,不能使用常规的逻辑表达式,如下所示,A1 是一个嵌套序列,但每一列 (列的描述不准确,只是为了直观形象) 元素都是升序的:

A B
1 =26.([char(~+64),~,date(202302,01)+~])
2 序列的序列用二分法查找时有以下限制:
3 1、表达式中不能使用 >,=,<
4 =A1.select@b(~(1)=="F") 需要返回值为整型的表达式
5 =A1.select@b(~(1)>"F") 需要返回值为整型的表达式
6 =A1.select@b(~(2)==6) 需要返回值为整型的表达式
7 =A1.select@b(~(2)>6) 需要返回值为整型的表达式
8 =A1.select@b(~(3)==date(202302,10)) 需要返回值为整型的表达式
9 =A1.select@b(~(3)>date(202302,10)) 需要返回值为整型的表达式
10
11 2、文本等于只能用冒号:(数字和日期可以用冒号和减号)
12 =A1.select@b(~(1):"F") 文本相等只能用冒号
13 =A1.select@b(~(2):6) 数值比较可以用冒号
14 =A1.select@b(~(2)-6) 数值比较可以用减号
15 =A1.select@b(~(3):date(202302,10)) 日期比较可以用冒号
16 =A1.select@b(~(3)-date(202302,10)) 日期比较可以用减号
17
18 3、大于等于小于等于只能用 between@b()
19 =A1.select@b(between@b(~(1),"F":"A")) 区间左大右小 大: 小 返回等于左边的值
20 =A1.select@b(between@b(~(1),"F":"J")) 闭区间正常表示
21 =A1.select@b(between@lrb(~(1),"F":"J")) 开区间
22 =A1.select@b(between@lrb(~(2),5:8)) 数字区间
23 =A1.select@b(between@b(~(2),5:inf())) 数字大于等于
24 =A1.select@b(between@b(~(2),-inf():5)) 数字小于等于

以上语句中 [A4:A9] 使用常规逻辑表达式是不能出结果的,会抛出错误“需要返回值为整型的表达式”,从 [A11:A24] 可以看到,对序列的序列使用二分查找只能用冒号或者减号或者 between@b(),并不像一开始提到的序表和序列的参数写法那么全面。所以,

问题 1:序列的序列使用二分法 select@b() 时,参数可否使用常规逻辑表达式,>、<、=、&&、||,实现序表、排列、序列、序列的序列在参数用法上的统一?

第二个问题是关于外存二分查找时的参数写法,file(btx,csv,txt).iselect(参数, 字段),其中的第一参数可以写成单值,或者一个有序的序列,或者用区间表达式 a:b。区间表达式可以写成 a:b 表示 a<= 字段值 <=b,也可以写成 :b,省略左边表示 字段值 <=b,或者写成 a:,省略右边表示 字段值 >=a。那如果要表示多种逻辑的组合呢,比如 字段值 <a || 字段值 >b,甚至是多个字段的复杂组合,按照目前的写法,似乎要写几次 [file.iselect( 条件 1),file.iselect(条件 2)…].conj(),所以,

问题 2:file(btx,csv,txt).iselect() 中的参数 1 可否使用常规逻辑表达式?

以上两个问题,恳请大佬们得闲时给予指导帮助,谢谢!