针对序列的每个成员做某种计算的函数称为循环函数,一般形式为A.f(x),实际上,序列的聚合运算也是循环函数。循环函数的计算行为由函数名决定,如sum表示求和、avg表示平均等等。在2.4.4函数中,已经对循环函数的一般使用做了说明,使用序表或排列时,可以在循环函数中使用字段或表达式等。
聚合运算
在聚合运算中,对序列或序表/排列中的每个成员循环计算,并根据函数计算结果,如:
|
A |
1 |
[2,5,-3,8] |
2 |
=A1.sum() |
3 |
=demo.query("select EID,NAME,SURNAME,GENDER, BIRTHDAY,STATE from EMPLOYEE") |
4 |
=A3.avg(age(BIRTHDAY)) |
5 |
=A3.count(STATE=="California") |
A2中用A.sum()函数,计算出序列成员的总和如下:
A4中用A.sum()函数计算序表中所有员工的平均年龄,A5中计算加州员工总数,A4和A5的结果如下:
聚合运算类的循环函数很多,还有A.min(),A.max(),A.ranks(),A.variance()等。
特别的,对于[x1, x2,…xn].f()这种样式的聚合运算,在没有歧义的情况下,也可以写为f([x1, x2,…xn])或f(x1, x2,…xn),如:
|
A |
1 |
[2,5,-3,8] |
2 |
=sum(A1) |
3 |
=sum(2,5,-3,8) |
4 |
=demo.query("select EID,NAME,SURNAME,GENDER, BIRTHDAY,STATE from EMPLOYEE") |
5 |
=avg(A4.(age(BIRTHDAY))) |
A2和A3中的计算结果和上一个例子中A2中结果相同。A5中的结果和上例A4中结果相同。
整数循环
对于需要循环指定次数的运算,可以用[1,2,3,…,n]这样的序列来循环计算。to(n).f(x)可以简写为n.f(x),称为整数循环,如:
|
A |
1 |
=10.sum() |
2 |
=demo.query("select EID,NAME,SURNAME,GENDER, BIRTHDAY,STATE from EMPLOYEE") |
3 |
=5.(A2(rand(500)).NAME) |
A1中计算出1至10的总和如下:
A3中随机选出5位员工,并列出他们的名字,结果如下:
嵌套
循环函数可以嵌套使用,即在计算表达式中再使用循环计算,类似A1.f1(A2.f2(x)) 这样的格式。在嵌套的循环函数中,~、#将解释为里层序列的当前成员和序号,而引用外层序列时需冠以序列名称,写作A.~、A.#。如:
|
A |
1 |
=demo.query("select EID,NAME,SURNAME,GENDER, BIRTHDAY,STATE from EMPLOYEE") |
2 |
=A1.group(year(BIRTHDAY)) |
3 |
=create(Year,Male,Female) |
4 |
>A2.run(A3.insert(0,year(BIRTHDAY),A2.~.count(GENDER== "M"),A2.~.count(GENDER=="F"))) |
A2中将员工数据按出生年份分组:
A3建立空序表准备存储计算结果。在A4中,循环分组后每年的数据,计算这一年中男员工和女员工的总数,将结果插入到结果序表中。在这里,执行后,可以在A3中查看到结果如下:
迭代函数
在循环函数计算中,会依次取出序列或排列中的成员,来执行某种计算,如果在计算过程中,需要根据已有的结果迭代计算,可以使用迭代函数。最基本的迭代函数是iterate(x,a;Gi,…),它需要在循环过程中调用,迭代时,会循环计算表达式x,而在其中可以用~~来调用已有的结果,并在计算后将x保存到~~,如果计算时设定的表达式Gi,…有变化,则x会根据a重新计算出初始值~~,如:
|
A |
1 |
=demo.query("select * from CITIES") |
2 |
=A1.sort(STATEID, left(NAME,1),CID) |
3 |
=A2.derive(iterate(~~+1, STATEID*100; STATEID):Code1) |
4 |
=A3.derive(iterate(~~+1, 0; STATEID,left(NAME,1)):Code2) |
A3和A4的表达式中,在用derive添加字段时,使用了迭代函数。A3函数中,iterate中对同一个州的城市顺序编号,而对每个州内,城市的初始值用州编码乘以100得到。A4继续用迭代函数添加字段Code2,iterate中对同一个州且城市名首字母相同的顺序编号,每次都从0开始重新编号。计算后,A4中的结果如下:
对于A4中的情况,每次都是累加计数,而且从0开始,迭代时可以用seq(Gi,…)来简写即如果把A4中的表达式修改为=A3.derive(seq(STATEID,left(NAME,1)):Code2),结果是相同的。
在迭代时,除了用seq,在未产生变化时依次计数,还可以使用rank(F;Gi,…)或ranki(F;Gi,…)根据指定表达式F的变化来排序,对于的记录,获得相同的编号如:
|
A |
1 |
=demo.query("select * from CITIES") |
2 |
=A1.sort(STATEID, left(NAME,1),CID) |
3 |
=A2.derive(iterate(~~+1, STATEID*100; STATEID):Code1) |
4 |
=A3.derive(seq(STATEID,left(NAME,1)):Code2) |
5 |
=A4.derive(rank(left(NAME,1);STATEID):Rank1) |
6 |
=A5.derive(ranki(left(NAME,1);STATEID):Rank2) |
A5中用迭代函数rank添加字段Rank1,A6中用迭代函数ranki添加字段Rank2,计算后,A6中的结果如下:
A5和A6的迭代计算中,函数中的参数Gi,…都只设定了STATEID,比较Rank1和Rank2可以发现,使用rank时,同一个州内的城市编号时,并列的编号会使后面的排名顺延;而使用ranki时,并列的编号只记为1个。
除了生成编码,用迭代函数还可以计算累计求和,如:
|
A |
1 |
=to(6) |
2 |
=A1.(iterate(~~+~*~)) |
3 |
=A1.(cum(~*~)) |
4 |
=to(10).iterate(~~+~*~,0,~>6) |
A2中,计算A1中数的累计平方和,结果如下:
在从0开始累计迭代时,可以用cum简写,A3中的结果和A2中是相同的。如果只需要最后的结果,可以使用A.iterate(x,a,c)函数,A4中,迭代计算累计平方和,至序列中的成员大于6为止。这样,A4中可以直接得到1至6的平方和,结果如下: