集算器可以很方便地实现常见的几种内存分组,比如等值分组、对位分组、枚举分组,下面用相应的例子来说明。

等值分组

等值分组的分组依据是本数据集的字段(或字段派生的计算列),每个组都是原数据集的子集。

例子描述:将销售订单按照订单年份进行分组。

数据描述:订单数据如下:

wKioL1QaT3XC3r4OAAE-JTg2ciQ626.jpg

上述数据集(序表)可以从数据库或文件读入,比如:

A1=file("E:/sales.txt").import@t()

集算器代码

    A2=A1.group(year(OrderDate))

计算结果

wKiom1QaT1zRxuiDAAIsaEgEhQU947.jpg

代码解读

  1. 本例中,分组依据来自于订单日期(OrderDate),通过year(OrderDate)可以将订单日期计算成年份,分组后每一年的数据归为一组。

  2. 分组字段可以是多个。比如重新按照年份、销售员分组,将不同年份不同销售员的数据归为一组,代码如下:

A1.group(year(OrderDate),SellerId)

3.  分组后的数据经常要进行聚合运算,比如根据A2计算出每年的销售额,代码如下:

A2.new(year(OrderDate):y,~.sum(Amount):a)

         计算结果是:

wKioL1QaT3XxxgJFAABcaHWNq00161.jpg

也可以将分组和汇总这两步用一个groups函数来实现:

A1.groups(year(OrderDate):y;sum(Amount):a)

当然,有时为了代码重用和提高计算效率,我们不得不把分组和汇总分开,比如对A2的其中一个组进行过滤,另一个组进行关联计算。再比如:汇总后发现某个分组的数据比较异常,值得深入研究,此时就可以利用原分组继续进行计算,而不是重新过滤出这个组的数据。

4.  缺省情况下,集算器的group函数将使用hash算法对数据分组,但对于已经有序的数据,使用相邻比对的方案会有更高性能,在group函数中使用@o选项可以实现这种分组方案,如:

A1.group@o(year(OrderDate),SellerId)

对位分组

    等值分组的分组依据来自于本数据集的字段,但有时分组依据会来自于外部,比如其他数据集的字段、用户构造的数组、参数列表等,这种分组方式就是对位分组。

    与等值分组不同,对位分组可能出现空子集,即没有任何成员与某个分组条目对应。而且还可能出现不完全分组,即有成员不出现在任何分组中。而等值分组是不可能出现这种情况的。

例子描述:已经计算出了绩效成绩前十的销售员列表,请按照该列表的顺序对订单进行分组。

分组前数据集

         订单沿用上一个例子,数据存储于A1中。

         绩效成绩前十的销售员,该列表存储于B1中,如下:

wKiom1QaT1yhO61yAABDpt_sRkU372.jpg

    销售员列表可以来自于中间表,也可以由一段代码计算生成,它的产生过程不是例子的重点。

集算器代码

     A1.align@a(B1:empID,SellerId)

计算结果

wKioL1QaT3Wh-CHEAAJNtQJ2pdE039.jpg

代码解读

  1. 本例中,分组依据(销售员列表)来自于被分组的数据集之外,分组后每个销售员的数据归为一组,组之间按照分组依据进行排列。

  2. 订单中的销售员要比列表中的多,这就会导致一部分订单不会出现在任何一个组,如果想把这些订单多分一组,可以使用函数选项@n,如下:

          A1.align@a@n(B1:empID,SellerId)

    多分的一组会排在最后,如下:

wKioL1QaT3WRr-7qAAB2WMKq034560.jpg

3.  有时候分组依据不在被分组的数据集中,比如分组依据是“新上岗的销售员列表”。这种情况下会使结果出现空组,这是正常的。比如把列表中的第一条改为empID=100,计算结果会是这样:

wKiom1QaT1zxd0b7AABnO5M2P-c573.jpg

枚举分组

枚举分组的分组依据更加灵活,可以是任意的布尔表达式,符合表达式的记录会归为相同的一组。

与对位分组类似,枚举分组也是不完全分组,可能出现空子集或成员不属于任何分组的情况,而且,枚举分组可能出现成员重复地属于多个分组的情况。

例子描述:将订单分为四组,分别是:A.订单金额小于1000的,B.金额小于2000之间的,C.金额在小于3000的,D.金额小于10000的。特别要求:数据不能重复分组,即如果某个订单已经属于前面的A组,则不能再将它分到后面的BCD组。

分组前数据集

         订单沿用上一个例子,数据存储于A1中。

集算器代码

         A2=["?<=1000","?<=2000","?<=3000","?<=10000"]

         A3=A1.enum(A2,Amount)

计算结果

wKiom1QaUEeD8p-CAAI3utN4wt4129.jpg

代码解读:

  1. 在本例中,分组依据是多个灵活的表达式。每条记录都会和表达式进行匹配,如果符合表达式,这条记录就会成为该组成员。同样的,组之间按照分组依据的顺序进行排列。

  2. 默认情况下,enum的分组结果是不会产生重复的,即分完A组的数据后,将从剩余的数据中判断是否符合表达B,上述例子就是这种分组方式。如果使用函数选项@r,则表示从全部的数据中判断是否符合表达式B,这就会产生重复的分组结果。比如:A3=A1.enum@r(A2,Amount),计算结果是:



wKioL1QaT3qyxiTmAAIMGz-j5ss317.jpg

3.  和对位分组类似,如果枚举表达式超出了待分组数据的范围,则该组为空。此外,有些数据不符合任何一个表达式,此时可以用@n函数选项把这些记录归为多余的一组。