7.10.4跨网游标的实际应用

跨网游标中通过调用网格执行计算,将结果返回成游标使用,这样,就可以利用网格中的代码解决一些比较复杂的数据处理工作。比如,在大数据分析处理中,经常会使用文本数据作为源数据。文本数据并不像数据库中的数据一样有着严格的规范,经常需要用程序去整理,此时使用跨网游标。

下面是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条记录构成排列。B2C2D2在最后一次循环中获取的数据分别如下:

其中,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中。如处理第一批数据时,B2C2中数据分别如下:

B7中,将C2中的每条数据用regex函数进行正则表达式解析,根据剩余的关键字SENDADDRESS:CONTENT:读取出所需数据作为字段。在处理第一批数据时,解析后B7中的结果如下:

B8中将每次的解析结果返回主程序。

 

这样,无论数据解析的过程多么复杂,在主程序中都只需要通过简单的跨网游标代码读取数据,和普通的游标数据使用起来没有什么区别:

 

A

1

=cursor("readMail.dfx")

2

=A1.fetch(1000)

3

>A1.close()

A2中读取出前1000条数据如下: