集算器如何处理文本计算——结构化运算
读入控制
从逗号分隔的有标题结构化文本D.csv中读入4列:name,sex,age,phone;其中phone是全数字但必须读成字符串类型。
|
A |
1 |
=file(“D.csv”).import@t(name,sex,age,phone:string;”,”) |
import函数有丰富的参数和选项控制是否有标题、分隔符、读入的列及其数据类型,大部分结构化文本的读入可以一句完成。
这个结果可以用JDBC以ResultSet对象的形式返回给Java主程序去再处理,这对熟悉JDBC的程序员很方便,相当于把文本当作数据库表读入。
文本很大时也可以用游标执行同样动作
|
A |
B |
1 |
=file(“D.csv”).cursor@t(name,sex,age,phone:string;”,”) |
|
2 |
=A1.fetch(100) |
取100行 |
游标也可以用JDBC返回给Java主程序。
大文本还可以用分段的方式读入:
|
A |
B |
1 |
=file(“D.csv”).import@tz(;”,”,2:4) |
平均分作4段,读入第2段 |
集算器按文件字节数分段保证读入效率(按行分段需要遍历前面所有行),对于分段点所在行采用了去头补尾的策略,即把本段第一行舍弃,最后一行补全,这样保证每一段都是由完整行构成的,不会出现半行的情况,确保信息的正确性。
游标也支持分段读入。
不关心读入次序时(求和计数等运算),还可以采用内置并行的方案提高性能:
|
A |
1 |
=file(“D.csv”).import@tm(name,sex,age,phone:string;”,”) |
这时集算器会启动多线程自动对文件分段后并行读入,因为文本解析较慢,采用并行读入能很大程度地利用CPU多核的能力,大幅度降低文本解析时间。
常规运算
从文本D.csv中找出男25岁以上、女23岁以上的人:1) 按姓名排序列出;2) 按性别分组计算平均年龄; 3) 列出所有出现过的姓氏(不考虑复姓)。
|
A |
B |
1 |
=file(“D.csv”).import@t(name,sex,age;”,”) |
|
2 |
=A1.select(sex==”M”&&age>=25||sex==”F”&&age>=23) |
过滤 |
3 |
=A2.sort(name) |
排序 |
4 |
=A2.groups(sex;avg(age):age) |
分组汇总 |
5 |
=A2.id(left(name,1)) |
唯一值 |
集算器提供了丰富的结构化计算功能,一定程度上可以将文本作为数据库表进行运算,在无数据库的场景下也能获得类似SQL的计算能力。
数据量大时这些计算也都可以基于游标工作:
|
A |
B |
1 |
=file(“D.csv”).cursor@tm(name,sex,age;”,”) |
|
2 |
=A1.select(sex==”M”&&age>=25||sex==”F”&&age>=23) |
过滤 |
3 |
=A2.sortx(name) |
排序 |
3 |
=A2.groups(sex;avg(age):age) |
分组汇总 |
3 |
=A2.groupx(left(name,1);) |
唯一值 |
4 |
=A3.fetch(…) |
取出结果 |
与内存运算不同的是,游标只能遍历一次,上述排序分组运算只能执行某一个,再执行另一个时需要重建游标。
用文本D.csv中phone列的第4至7位可到文本P.txt中aid列查出该号码的所在地area列,列出D.csv中电话号码所在地是北京的记录。
|
A |
1 |
=file(“D.csv”).import@tm(;”,”) |
2 |
=file(“P.txt”).import@t(id,area) |
3 |
=A1.derive(mid(phone,4,3):aid).switch(aid,A2:aid) |
4 |
=A3.select(aid.area==”Beijing”) |
将A1改成用游标也可以针对大文本工作。
集算器用指针处理外键连接,引用更方便。也可以用类似SQL的join方法:
|
A |
B |
1 |
=file(“D.csv”).import@tm(;”,”) |
|
2 |
=file(“P.txt”).import@t(id,area) |
|
3 |
=join@1(A1,left(phone,4,3);A2,aid) |
@1表示左连接 |
4 |
=A3.select(#2.area==”Beijing”).(#1) |
|
文件比对
找出文本T1.txt中id列在T2.txt中出现和不出现的值。
|
A |
B |
1 |
=file(“T1.txt”).import@ti(id) |
|
2 |
=file(“T2.txt”).import@ti(id) |
|
3 |
=A1^A2 |
交集,即T1和T2共有的值 |
4 |
=A1\A2 |
差集,即T1中有而T2中没有的值 |
比对列值直接用集合交差运算即可。
找出文本T1.txt中id列在T2.txt中出现和不出现的行。
|
A |
B |
1 |
=file(“T1.txt”).import@t().sort(id) |
|
2 |
=file(“T2.txt”).import@t().sort(id) |
|
3 |
=[A1,A2].merge@i(id) |
交集,T1的行,其id在T2中也有 |
4 |
=[A1,A2].merge@d(id) |
差集,T1的行,其id在T2中没有 |
要获得整行需要先排序再用归并法。
找出文本T1.txt和T2.txt中哪些行的id值相同但其它列不同的行:
|
A |
B |
1 |
=file(“T1.txt”).import@t() |
|
2 |
=file(“T2.txt”).import@t() |
|
3 |
=join(A1,id;A2,id) |
用等值连接,不匹配的丢弃 |
4 |
=A3.select(cmp(#1,#2)!=0) |
找出记录不同的 |
用join可以将数据按某列对齐。
不能装下内存的大文本也可以使用归并和连接的方法比对,但都需要先排序:
|
A |
B |
1 |
=file(“T1.txt”).cursor@t().sortx(id) |
|
2 |
=file(“T2.txt”).cursor@t().sortx(id) |
|
3 |
=[A1,A2].merge@xi(id) |
交集,T1的行,其id在T2中也有 |
4 |
=[A1,A2].merge@xd(id) |
差集,T1的行,其id在T2中没有 |
merge@x表示针对有序的游标归并,大文件外存排序要用sortx()。
|
A |
B |
1 |
=file(“T1.txt”).cursor@t().sortx(id) |
|
2 |
=file(“T2.txt”).cursor@t().sortx(id) |
|
3 |
=join@x(A1,id;A2,id) |
用等值连接,不匹配的丢弃 |
4 |
=A3.select(#1.array()!=#2.array()) |
|
join@x表示针对有序的游标连接。
posted on 2015-10-27 08:50 hivehooker 阅读(372) 评论(0) 编辑 收藏 举报