跨网游标中通过调用网格执行计算,将结果返回成游标使用,这样,就可以利用网格中的代码解决一些比较复杂的数据处理工作。比如,在大数据分析处理中,经常会使用文本数据作为源数据。文本数据并不像数据库中的数据一样有着严格的规范,经常需要用程序去整理,此时使用跨网游标。
下面是D:\files\EmployeeMul.txt中的员工数据:
1 |
Nicole Jones |
F |
2009-08-01 |
1990-01-03 |
Philadelphia |
Pennsylvania |
Production |
36801 |
NicoleJones_PA@mail.xxx |
|
|
2 |
Tammy Powell |
F |
2010-09-29 |
1992-07-31 |
Pittsburgh |
Pennsylvania |
Technology |
43711 |
TammyPowell2@mail.xxx |
|
|
3 |
Jack Anderson |
M |
2007-04-12 |
1984-08-26 |
Cleveland |
Ohio |
R&D |
36094 |
JackAnderson_OH@mail.xxx |
|
|
4 |
Margaret Morales |
F |
2014-03-18 |
1992-11-12 |
Washington |
Washington |
Sales |
48983 |
MargaretMorales4@mail.xxx |
|
|
5 |
Willie Roberts |
M |
2012-07-06 |
1988-07-01 |
Plano |
Texas |
Technology |
43711 |
WillieRoberts5@mail.xxx |
|
|
6 |
Todd Gray |
M |
2009-01-04 |
1981-09-06 |
Baltimore |
Maryland |
R&D |
36094 |
ToddGray_MD@mail.xxx |
|
|
7 |
Kevin White |
M |
2007-04-19 |
1986-07-10 |
Minneapolis |
Minnesota |
Technology |
43711 |
KevinWhite_MN@mail.xxx |
|
|
…...
|
|
|
|
在这个文本数据中,每位员工的数据分为3行,包括员工编号、姓名、性别、录用日期、生日、所在城市等信息。将字段较多的一条记录拆分为多行,这样的存储方式,在文本数据中比较常见。现在,需要从中选择出费城的员工资料。
由于在集算器中直接引入文本数据作为序表或游标时,是要求文件中的每行数据作为1条记录的,因此这样的文本数据不能直接使用。如果需要根据EmployeeMul.txt中的数据来分析计算,需要将数据重新整合。此时,如果使用跨网游标,则能使问题变得更为直观。首先,在mergeRecord.dfx中处理数据:
|
A |
B |
C |
D |
1 |
=file("EmployeeMul.txt").cursor() |
|
|
|
2 |
for A1,5000*3 |
=A2. step(3,1) |
=A2. step(3,2) |
=A2. step(3,3) |
3 |
|
=join@p(B2:L1;C2:L2;D2:L3) |
=B3.new(L1.#1:ID,L1.#2:Name,L1.#3:Gender, L1.#4:EntryDate,L2.#1:Birthday,L2.#2:City, L2.#3:State,L2.#4:Dept,L3.#1:SuperiorID, L3.#2:MailAdress) |
|
4 |
|
return C3 |
|
|
在A1中,将文本文件读为游标。在A2中每次读取5000*3条记录,并在语句块中将数据合并。其中,在每3条记录中,B2取出第1条记录构成排列,C2取出第2条记录构成排列,D2取出第3条记录构成排列。B2,C2和D2在最后一次循环中获取的数据分别如下:
其中,D2中的数据只有前两列有效。在B3中,用join@p函数将上面三个序表中的记录横向连接:
这样,在C3中就可以使用这些初始数据,生成所需的记录了:
通过跨网游标调用mergeRecord.dfx,就能简单完成所需处理的计算:
|
A |
1 |
=cursor("mergeRecord.dfx") |
2 |
=A1.select(City=="Philadelphia") |
3 |
=A2.fetch() |
通过跨网游标,将较复杂的多行记录处理在子网格中完成,使得程序目的明确,简洁易读。同时,用游标来操作,可以很方便地完成大数据文件的分析计算。例子中的数据量并不很大,在A3中,一次读出所有费城的员工数据如下:
有时,存储在文本中的数据,不仅需要将多行数据合并为一条记录,同时结构也更为复杂。如下面的D:\files\mailInfo.txt:
文档中,简单存储了一些邮件的内容,包括收件人地址,发件人地址及邮件正文,分别用RECIPIENT:,SENDADDRESS:和CONTENT:作为开头。其中,邮件正文的行数是不定的,因此这样的数据无法读出指定行数的数据合并处理,更无法直接使用。在集算器中,同样可以使用跨网游标,先在readMail.dfx中处理数据:
|
A |
B |
C |
1 |
=file("mailInfo.txt").cursor@s() |
>A1.skip(2) |
="" |
2 |
for A1,5000 |
=C1+A2.(#1).concat("\r\n") |
=B2.split("RECIPIENT:") |
3 |
|
if A1.fetch@0(1) |
=C2.len() |
4 |
|
|
>C1="RECIPIENT:"+C2(C3)+"\r\n" |
5 |
|
|
>C2=C2.to(2,C3-1) |
6 |
|
else |
>C2=C2.to(2) |
7 |
|
=C2.regex("(.+)[\\s\\S]+SENDADDRESS:(.+)[\\s\\S]+CONTENT:([\\s\\S]+)";Recipient,SendAddress,Content) |
|
8 |
|
return B7 |
|
A1中用文本文件建立游标。由于文本中前两行数据无效,因此在B1中跳过。由于文件数据中,到底多少行数据正好能够构成一条记录是无法确定的,因此需要考虑,C1中存储循环时未处理的剩余数据。
在A2中,循环读取游标,每次处理5000行数据。在B2中,读入的数据连接成一个大字符串,如果上次循环中有未处理的数据,置于数据最前方。每条邮件记录都是以RECIPIENT:开始的,因此在C2中根据这一点将大字符串按邮件拆分。在刚拆分完的序列中,第一个成员将是空行,而最后一个数据无法确定是否已读取完成。因此在3~7行继续处理数据。在B3中的cs.fetch@0()使用了@0选项,此时并不会实际取数,而是判断游标中的数据是否已全部读出。如果未读取完成,则将最后的数据存储在C1中。如处理第一批数据时,B2和C2中数据分别如下:
在B7中,将C2中的每条数据用regex函数进行正则表达式解析,根据剩余的关键字SENDADDRESS:和CONTENT:读取出所需数据作为字段。在处理第一批数据时,解析后B7中的结果如下:
在B8中将每次的解析结果返回主程序。
这样,无论数据解析的过程多么复杂,在主程序中都只需要通过简单的跨网游标代码读取数据,和普通的游标数据使用起来没有什么区别:
|
A |
1 |
=cursor("readMail.dfx") |
2 |
=A1.fetch(1000) |
3 |
>A1.close() |
在A2中读取出前1000条数据如下: