循环运算
1. 循环比较每行记录判断文件是否相同循环判断,每次在序列最后添加新的成员。【例 1】 比较两个行数相同的文件中有多少行数据完全一致。文件部分数据如下:IDPredicted_YOriginal_Y100.0123884643676080930.0110.015198991239789880.0130.00079202388850612480.0190.00126563674681591020.0210.0094605459974733790.0230.0241767918716816640.0………【SPL脚本】ABC1=file("p_old.csv").import@ct()/读取第一次输出的文件2=file("p_new.csv").import@ct()/读取第二次输出的文件3for A1.len()=cmp(A1(A3),A2(A3))/循环比较两个文件同行记录的数据4=@|B3/把每次比较的结果与 B4 格值合并5=B4.count(~==0)/统计有多少行数据相等A5的执行结果如下:Value113022. 循环赋值对集合的成员进行循环计算并赋值。【例 2】 在销售表中,将 2014 年前 10% 的销售员再给予 5% 的业绩奖励。销售表部分数据如下:OrderIDCustomerSellerIdOrderDateAmount10400EASTC12014/01/013063.010401HANAR12014/01/013868.610402ERNSH82014/01/022713.510403ERNSH42014/01/031005.910404MAGAA22014/01/031675.0……………【SPL脚本】AB1=connect("db").query("select * from sales")/连接数据源,读取销售表2=A1.select(year(OrderDate)==2014)/选出 2014 年数据3=A2.groups(SellerId;sum(Amount):Amount)/按销售员分组汇总当年销售总额4=A3.sort@z(Amount).to(A3.len()*0.1)/按销售额降序排列,取前百分之十5=A4.run(Amount*=1.05)/使用函数 A.run(),对前百分之十循环,每人给予销售额 5% 的奖励A5的执行结果如下:SellerIdAmount4150433.1853127878.041102756.759887965.3463. 复杂跨行计算分组统计数据后,对每组分列统计不同的结果,同时跨行计算。【例 3】根据用户支付数据明细表,统计各个用户 2014 年每月应付金额的汇总表。用户支付数据明细表部分数据如下:IDcustomIDnameamount_payabledue_dateamount_paidpay_date112101C013CA128002014-02-21128002014-12-19112102C013CA35002014-06-1535002014-12-15112103C013CA26002015-03-2169002015-10-17要求根据指定年份(如2014),输出每月应付金额,若无当月数据,则当月应付金额为上月该值:name123456789101112CA1280012800128001280016300163001630016300163001630016300…【SPL脚本】ABC1=file("Payment.txt").import@t().select(year(due_date)==2014)/从文件中导入 2014 年数据2=create(name,${12.().concat@c()})=A1.group(customID)/A2:生成包含 12 个月的空表。A3:按客户 ID 分组。3for B2=12.(null)/生成 12 个月的空数据4>A3.run(B3(month(due_date))= amount_payable)/设置相应月份的应付金额。5>B3.run(~+=~[-1])/将空值置为前一个月的数值,新增应付款项时累加。6=A2.record(B2.name|B3)/将记录插入结果表中。A2的执行结果如下:name123456789101112CA1280012800128001280016300163001630016300163001630016300…4. 最大连续增长天数在循环计算中,计算某列的连续增长次数。【例 4】 根据上证指数记录,求 2019 年收盘价增长的最大连续天数。上证指数表部分数据如下:DateOpenCloseAmount2019/12/313036.38583050.1242.27E112019/12/302998.16893040.02392.67E112019/12/273006.85173005.03552.58E112019/12/262981.24853007.35461.96E112019/12/252980.42762981.88051.9E11…………【SPL脚本】AB1=file("000001.csv").import@ct()/导入数据文件2=A1.select(year(Date)==2019).sort(Date)/选出 2019 年的记录并按日期排序3=n=0,A2.max(if(Close>Close[-1],n+=1,n=0))/循环收盘价,比较每天的收盘价和前日收盘价,如果当日收盘价更高,则计数加 1,最后选出计数最大值。A3的执行结果如下:Value65. 嵌套循环嵌套使用循环函数计算。【例 5】 百鸡问题,鸡翁一值钱五,鸡母一值钱三,鸡雏三值钱一。百钱买百鸡,问鸡翁、母、雏各几?【SPL 脚本】AB1=to(100/5)/可能购买的鸡翁数量2=to(100/3)/可能购买的鸡母数量3=33.(~*3)/可能购买的鸡雏数量4=create(Cock,Hen,Chick)/创建空表用于存放三种鸡的数量5>A1.run(A2.run(A3.run(if(A1.~+A2.~+A3.~==100 && A1.~*5+A2.~*3+A3.~/3==100,A4.insert(0,A1.~,A2.~,A3.~)))))/分别循环鸡翁、鸡母、鸡雏,当满足百钱买百鸡时,将结果插入到 A4 创建的集合中。其中用到了 ~ 符号代表集合循环的当前成员A4的执行结果如下:CockHenChick4187881181124846. 循环中调用次数循环查找文本,并按需要生成结果,循环中需要使用循环次数。【例 6】 根据文本 1 中的关键词,在文本 2 中查找,希望整理为输出结果:
【SPL 脚本】AB1=file("file1.txt").read@n()/读取文本 12=file("file2.txt").read@n()/读取文本 23=A1.conj(("Q"+string(#)+"."+~)|A2.select(pos(~,A1.~)).(~.words()(1)))/循环文本 1 中的字符串,在文本 2 中查找,并取第一个英文单词。A2.select 中用到了 ~ 代表 A2 当前成员,A1.~ 代表 A1 的当前成员。每组搜索结果前拼上 Q+A1 的序号 +A1 当前成员,其中序号通过 #取得。A3的执行结果如下:MemberQ1. like parksIShellyHarryQ2. went outShellyQ3. go outIBenHarry7. 循环时按位置统计临近数据循环计算,计算时按位置计算偏移区间内均值。【例 7】 根据招商银行的股市交易表,列出 2020 年 1 月 1 日至 10 日每天的 20 日收盘均价。股市交易表部分数据如下:DateOpenCloseAmount2019/12/313036.38583050.1242.27E112019/12/302998.16893040.02392.67E112019/12/273006.85173005.03552.58E112019/12/262981.24853007.35461.96E112019/12/252980.42762981.88051.9E11…………【SPL脚本】AB1=connect("db")/连接数据源2=A1.query("select Date, Close from Stock where Code='600036'order by Date")/选出招商银行数据并按日期排序3=A2.pselect@a(Date>=date("2020/01/01") && Date<=date("2020/01/10"))/使用函数 A.pselect() 获取 2020 年 1 月 1 日到 10 日对应记录的序号4=A2(A3).derive(A2.calc(A3(#),avg(Close[-19:0])):ma20)/使用函数 calc() 循环计算前十日数据的 20 日均值并返回,计算时使用了 Close[-19:0 获取从过去 19 天到今天的收盘价。A4的执行结果如下:DateClosema202020/01/0238.8837.352020/01/0339.437.502020/01/0639.2437.642020/01/0739.1537.792020/01/0838.4137.902020/01/0938.938.032020/01/1039.0438.168. 迭代累加循环时迭代累加,根据累加值筛选。【例 8】根据销售表,统计出 2014 年每个月达到 20 笔订单所需天数。销售表部分数据如下:OrderIDCustomerSellerIdOrderDateAmount10400EASTC12014/01/013063.010401HANAR12014/01/013868.610402ERNSH82014/01/022713.510403ERNSH42014/01/031005.910404MAGAA22014/01/031675.0……………【SPL脚本】AB1=connect("db").query("select * from sales")/连接数据源,读取销售表2=A1.select(year(OrderDate)==2014)/选出 2014 年数据3=A2.sort(OrderDate)/按照订单日期排序4=A3.select(seq(month(OrderDate))==20)/使用函数 seq() 计算每个月份的订单序号,并选出每个月序号为 20 的记录A4的执行结果如下:MonthDay120220320418……9. 分组计算排名循环中计算分组中的排名。【例 9】根据员工收入表,求员工在本部门的收入排名。员工收入表部分数据如下:IDNAMEDEPTSALARY1RebeccaR&D70002AshleyFinance110003RachelSales90004EmilyHR70005AshleyR&D16000…………【SPL 脚本】AB1=connect("db") .query("select * from Employee order by DEPT, SALARY DESC")/连接数据源,读取员工表并按部门和收入排序2=A1.derive(rank(SALARY;DEPT):DeptRank)/对有序的部门和收入利用函数 rank() 编号,计算出各部门排名A2的执行结果如下:IDNAMEDEPTSALARYDeptRank2AshleyFinance11000132AndrewFinance110001230HannahFinance10000324ChloeFinance100003……………10. 分组计算紧凑排名循环计算分组中的紧凑排名。【例 10】根据成绩表,求出一班学生 ID 为 8 的学生的各科成绩在本班的排名。成绩表部分数据如下:CLASSSTUDENTIDSUBJECTSCOREClass one1English84Class one1Math77Class one1PE69Class one2English81Class one2Math80…………【SPL 脚本】AB1=connect("db") .query("select * from SCORES where CLASS='Class one'order by SUBJECT, SCORE DESC")/连接数据源,读取学生成绩表并按学科和成绩排序2=A1.derive(ranki(SCORE;SUBJECT):Rank)/对有序的学科和成绩利用函数 ranki() 计算各科成绩的紧凑排名3=A2.select(STUDENTID==8)/选出学生 ID 是 8 的学生信息4=create(${A3.(SUBJECT).concat@c()}).record(A3.(Rank))/利用 A3 选出的结果,整理出各科紧凑排名A4的执行结果如下:EnglishMathPE1041411. 迭代求和循环计算迭代求和的结果。【例 11】根据上证指数表,计算 2019 年每个交易日的全年累计成交金额。上证指数表部分数据如下:DateOpenCloseAmount2019/12/313036.38583050.1242.27E112019/12/302998.16893040.02392.67E112019/12/273006.85173005.03552.58E112019/12/262981.24853007.35461.96E112019/12/252980.42762981.88051.9E11…………【SPL 脚本】AB1=file("000001.csv").import@ct()/导入数据文件2=A1.select(year(Date)==2019).sort(Date)/选出 2019 年的记录并按日期排序3=A2.derive(cum(Amount):CUM)/使用 cum() 函数计算累计成交金额A3的执行结果如下:DateOpenCloseAmountCUM2019/01/022497.88052465.2919.759E109.759E102019/01/032461.78292464.36281.07E112.046E112019/01/042446.01932514.86821.39E113.436E112019/01/072528.69872533.08871.46E114.896E112019/01/082530.30012526.46221.23E116.126E11……………12. 自定义迭代计算循环中使用迭代计算,自行设置迭代中的计算表达式和终止条件。【例 12】根据销售表数据,统计 2014 年第一季度到哪一天完成了销售总额 15 万的季度目标。销售表部分数据如下:OrderIDCustomerSellerIdOrderDateAmount10400EASTC12014/01/013063.010401HANAR12014/01/013868.610402ERNSH82014/01/022713.510403ERNSH42014/01/031005.910404MAGAA22014/01/031675.0……………【SPL脚本】AB1=connect("db").query("select * from sales")/连接数据源,读取销售表2=A1.select(year(OrderDate)==2014)/选出 2014 年数据3=A2.iterate((@+=Amount, ~~=OrderDate),0,@>150000)/使用函数 iterate() 迭代计算,初始值为 0。将销售额累加到当前格,直到超过 15 万终止。函数返回订单日期。A3的执行结果如下:Value2014/03/25《SPL CookBook》中还有更多相关计算示例。