集算器如何处理文本计算难题

文本可以说是除了数据库外几乎最常见的数据存储形式,针对文本的计算非常重要。然而文本本身没有计算能力,不象数据库有SQL语法,这样对文本的计算就需要借助程序设计语言编码,而大多数用于文本处理的程序语言都没有集合化的,编写批量运算时很繁琐。比如用Java写个很简单地求和运算就要很多行,如果涉及到过滤分组这种运算就需要几百行代码。近年来新出来的perl,python,R等脚本语言在这些方面有所改善,但对批量结构化计算的支持仍然不足,而且集成性也较差。

还有一种方案是将文本数据导入数据库再利用SQL计算,但文本经常缺乏数据库要求的强数据类型特征,导入过程常常要伴随繁琐的数据整理,而且多了一个步骤,事务的处理效率也会受到严重影响。

作为集合化的动态脚本语言,集算器一定程度地弥补这方面的缺失。这里将列举一些文本计算中常见的情况,说明集算器实施这类计算的优势。

无结构运算

文本解析

文本T.txt的行内数据项由不确定数量的空格分隔开:

20010-8-13 991003 3166.63 3332.57  3166.63  3295.11

2010-8-10 991003 3116.31 3182.66  3084.2   3140.2

……

现在要计算每行最后四项数据的平均值列表。用集算器只要一句:


A


1


=file("T.txt")[email protected]().([email protected](“”).to(-4).avg())

[email protected]()将文本读入成字串集合,[email protected](“”)将字串按不定数量的空白符拆成子串集合,@p将自动解析成合适的数据类型以便进一步计算(这里计算平均)。

将逗号分隔符文本T.csv中行内数据项数不少于8项的行的前8项写出成另一个文本R.txt,分隔符替换成|(某些银行系统采用的分隔符):


A


1


=file("T.csv")[email protected]().(~.array(“,”)).select(~.len()>=8)


2


>file(“R.txt”).write(A1.(~.to(8).string(“|”)))

string()函数可将集合按指定分隔符再拼成字串。

文本T.txt中都是形如下行的串,需要按字符US前的州名(LA)分组拆分成多个文件。

COOP:166657,‘NEW IBERIA AIRPORT ACADIANA REGIONAL LA US‘,200001,177,553

……


A


1


=file("T.txt")[email protected]()


2


=A1.group(mid(~,pos(~," US‘")-2,2):state;~:data)


3


>A2.run(file(state+".txt").export(data))

集算器也提供了对正则表达式的支持以应对复杂的拆解需求。不过由于正则表达式的使用难度较大且性能较差,一般建议仍然用常规方法实现。

结构化

日志S.log中每3行构成一段完整信息,需要将其解析成结构化数据后再到T.txt:


A


B


1


=file(“S.log”)[email protected]()


2


=create(…)


建立目标结果集


3


for A1.group((#-1)\3)



按行号分组,每3行一个单位




从A3(这3行)中解析出字段值



>A2.insert(…)


插入到目标结果集



>file(“T.txt”).export(A2)


写出结果

有了按行号分组的机制,就可以用循环每次处理一组数据,简化难度。

显然,更简单的单行情况是其特例。

如果S.log大到不能读入内存,也可以使用游标逐步读入并写出:


A


B


1


=file(“S.log”)[email protected]()


创建游标用流式读入文件


2


=file(“T.txt”)


结果文件


3


for A1,3



每读入3行执行一轮循环




从A3(这3行)中解析出字段值



>[email protected](...)


追加写到文件中

熟悉的用户还可以优化代码,使得解析多条记录后一次写出,会有更好的性能。

日志S.log中每段完整信息均以”---start---“开头,包含行的数量不确定。这时只要将前面的A3格改成:


3


for [email protected](~==”---start---”)


出现---start---时会产生一个新分组

类似地,大文本时也可以用游标处理,也是将上面A3格改成:


3


for A1;~==”---start—“:0


出现---start---时另起一轮循环

不定行还有一种情况,同一段信息的每一行都有相同的前缀(比如该段日志所属的用户号等),当这个前缀发生变化时就表示开始另一段信息了,这时仍然只要简单地修改A3代码即可处理:


3


for [email protected](left(~,6))


前6个字符变化时产生一个新组


3


for A1;left(~,6)


前6个字符变化时另起一轮循环

前一小节的运算也可以改造成使用游标支持大文本。

查找统计

在目录下所有文本中找出含有指定单词的文件,并列出所在行内容及行号:


A


1


[email protected](“*.txt”)


2


=A1.conj(file(~)[email protected]().(if(pos(~,"xxx"),[A1.~,#,~].string())).select(~))

grep是常用的unix命令,但有些操作系统下没有,且在程序中实现也不简单。集算器提供了文件系统的遍历功能,结合文本计算能力,只要两句代码就能完成。

列出文本T.txt中所有出现过的单词及次数,忽略大小写:


A


1


=lower(file(“T.txt”).read()).words().groups(~:word;count(1):count)

WordCount是著名的练习题,集算器提供了words()函数将串拆分成单词,只要一句就可以完成这个运算。

列出文本T.txt包括字母a,b,c的所有单词,忽略大小写:


A


1


=lower(file(“T.txt”).read()).words().select(~.array(“”).pos([“a”,”b”,”c”]))

由于次序问题,判断字母包含不能用子串查找,要用array(“”)将串拆成单字符集合,再用集合从属去判断。有集合运算支持的集算器也只要一句即可。

这些运算都可以用分段或游标的方式简单改造以支持大文本。

时间: 2024-10-12 19:54:06

集算器如何处理文本计算难题的相关文章

集算器如何处理类文本数据计算

json Java有足够多的类库用于解析和生成json,但缺乏后续计算能力.集算器支持多层结构数据,可以不丧失信息地将json解析成可计算的内存数据表进一步处理. 设有如下格式的json数据: { “order”:[ { “client”:”北京润乾软件”, “date”:”2015-6-23”, “item” : [ { “product”:”HP笔记本”, “number”:4, “price”:3200 }, { “product”:”DELL服务器”, “number”:1, “pric

集算器协助MongoDB计算之数位比较

Mongodb脚本解决复杂问题的计算能力有限,直接使用时较为吃力.很多情况下需要将数据读出后在主程序中进一步完成运算,而在Java等高级语言中编写这类集合式运算也比较麻烦.这时可以用集算器esProc来辅助,本文通过例子来说明使用方法. Mongodb中有一个test集合如下: >db.test.find({},{"_id":0}) {"value" : NumberLong(112937552) } {"value" : NumberLo

集算器协助MongoDB计算之交叉汇总

MongoDB实现交叉汇总比较困难,如果将数据取出,用Java等高级语言来汇总的话,也相当复杂.因此,可以考虑用集算器esProc辅助MongoDB完成交叉汇总.下面我们通过一个例子来看一下具体做法. Student集合如下: db.student.insert  ( {school:'school1', sname : 'Sean' , sub1:4, sub2 :5 }) db.student.insert  ( {school:'school1', sname : 'chris' , su

集算器协助MongoDB计算之本地化排序

对于本地化语言(例如:中文),MongoDB是按照UNICODE编码排序,而不是根据本地语言的编码排序.用esProc结合MongoDB可以方便的实现本地化语言的排序(例如:中文按照拼音排序).下面我们以中文为例,来看一下具体做法. MongoDB中的集合person保存了姓名和性别如下: >db.person.find() {"_id" : ObjectId("544e4e070f03ad39eb2bf498"),"name" : &qu

集算器协助Java处理结构化文本之分组汇总

直接用Java实现文体文件分组汇总会有如下的麻烦: 1.文件不是数据库,不能用SQL访问.当分组.汇总表达式变化时,只能改写代码.而要实现灵活表达式的话,需要自己实现动态表达式解析和求值,编程工作量非常大. 2.遍历过程中记录分组结果,结果小了还可以存在内存中,如果分组结果太大时要将中间结果缓存进临时文件再归并,实现过程非常复杂. 使用集算器辅助Java编程,这些问题都有现成的类库可以解决.下面,我们通过例子来看一下具体作法. 文本文件employee.txt中保存有员工信息,我们要按照DEPT

集算器协助Java处理结构化文本之条件过滤

直接用Java实现文本文件中数据按条件过滤会有如下的麻烦: 1.文件不是数据库,不能用SQL访问.当过滤条件变化时需要改写代码.如果要实现象SQL那样灵活的条件过滤,则需要自己实现动态表达式解析和求值,编程工作量非常大. 2.文件太大时不能一次性装入内存处理,而采用逐步读入方式在考虑到性能时又会涉及到文件缓冲区管理.拆行计算等复杂编程. 使用集算器来辅助Java编程,这些问题都不需要自己写代码解决.下面我们通过例子来看一下具体作法. 文本文件employee.txt中保存了员工数据.我们要读取员

集算器如何优化复杂报表计算(2)格式布局及过程计算

布局格式 横向分栏 大多数报表工具都支持纵向分栏,但几乎没有报表工具支持横向分栏,我们可以用集算器把数据集事先摆好. A B C 1 =db.query("select a,b,c from T ") 2 =A1.step(3,1) =A1.step(3,2)|[null] =A1.step(3,3)|[null] 3 =A2.derive(B2(#).a:a2,B2(#).b:b2,B2(#).c:c2,C2(#).a:a3,C2(#).b:b3,C2(#).c:c3) 这段代码将3

集算器用作Java结构化文件计算类库

有时我们不能使用数据库而采用文件系统存储数据,这时就需要自行完成基于文件的数据计算.但JAVA本身缺少相应的类库,需要硬编码才能实现结构化文件计算,代码复杂且可读性差.在网上有许多寻找用于文件计算的Java类库的问题,如: http://www.coderanch.com/t/561180/java/java/read-text-file-perform-operation http://stackoverflow.com/questions/9614112/how-to-sort-and-ar

用集算器协助Java读入文本

JAVA提供了最基本的文件处理函数,可以简单无结构的方式读入小文本文件,如果遇到需要结构化.格式多样.要求特殊的文件或内存装不下的大文件,相应的代码就会很复杂,可读性和复用性也很难保障. 使用免费的集算器可以弥补这一不足.集算器封装了丰富的结构化文件读写和计算函数,并提供JDBC接口.JAVA应用程序可以将集算器脚本文件当做数据库存储过程执行,传入参数并用JDBC获得返回结果.详情参考集算器用作Java计算类库的应用结构. 下面说明JAVA读入文本的常见案例,以及集算器对应的解法. 读入指定列