Chinaunix首页 | 论坛 | 博客

-

  • 博客访问: 4132618
  • 博文数量: 172
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1923
  • 用 户 组: 普通用户
  • 注册时间: 2018-12-20 14:57
文章分类
文章存档

2021年(19)

2020年(81)

2019年(68)

2018年(4)

我的朋友

分类: 敏捷开发

2020-11-18 14:48:40

在数据处理业务中,有时需要比较两个文本文件内容有哪些相同或不同的数据,本文将介绍文本文件比对的几种情况,如整行比对、关键列比对,同时又分小文件、大文件比对,并提供用 esProc SPL 编写的代码示例。esProc 是专业的数据计算引擎,SPL 中有一套完善的集合运算领域的函数库,做文件比对很方便,写出的代码非常简洁。

 

1.   小文件比对

1.1  整行比对

有两个文本文件,其每一行是一个字符串,要对这两个文件中整行内容进行比对。处理此问题可以把文件的每一行读成一个字符串,组成一个集合,然后通过两个集合的运算得出结果。

报名绘画、舞蹈兴趣班的同学学号姓名分别记录在paint.txtdance.txt中,paint.txt部分数据如下所示:
    20121102-Joan
    20121107-Jack
    20121113-Mike

 

1.1.1.   找相同

把两个文件中整行内容相同的行都找出来,即求两集合的交集。

示例:请找出报了这两个兴趣班的所有同学,记录在p_d.txt文件中。

esProc SPL脚本如下:


A 注释
1 =file("e:/txt/paint.txt").read@n() 读出paint.txt的每一行组成集合
2 =file("e:/txt/dance.txt").read@n() 读出dance.txt的每一行组成集合
3 =file("e:/txt/p_d.txt").write(A1^A2) A1A2集合的交集写入文件p_d.txt

 

1.1.2.  找不同

找不同有以下两种情况:

1、  找出两个文件中所有不相同的行。

示例:找出所有只报了一个兴趣班的同学, esProc SPL脚本如下:


A 注释
1 =file("e:/txt/paint.txt").read@n() 读出paint.txt的每一行组成集合
2 =file("e:/txt/dance.txt").read@n() 读出dance.txt的每一行组成集合
3 =file("e:/txt/p_d.txt").write(A1%A2) A1A2集合的异或集写入文件p_d.txt

 

2、找出一个文件中有而另一个文件中没有的行。

示例:找出只报了绘画班的同学和只报了舞蹈班的同学, esProc SPL脚本如下:


A 注释
1 =file("e:/txt/paint.txt").read@n() 读出paint.txt的每一行组成集合
2 =file("e:/txt/dance.txt").read@n() 读出dance.txt的每一行组成集合
3 =file("e:/txt/p_1.txt").write(A1\A2) 将绘画班A1减去舞蹈班A2所得的差集,即只报了绘画班的同学,写入文件p_1.txt
4 =file("e:/txt/d_1.txt").write(A2\A1) 将舞蹈班A2减去绘画班A1所得的差集,即只报了舞蹈班的同学,写入文件d_1.txt

 

1.2  关键列比对

两个文本文件,有多列数据,第一行是列名,第二行开始是数据记录,要对两个文件中关键列的内容进行比对。处理此问题可以把文件读成数据集,取出关键列的记录值组成一个集合,然后通过两个集合的运算得出结果。

20182019年的销售订单表order_2018.txtorder_2019.txt,两文件有相同的列结构,部分数据如下所示:

    ..

 

1.2.1.   找相同

把两个文件中关键列值相同的都找出来。

示例:请找出这两年都购买了同一种产品的用户CustomerId和产品ProductId,记录在c_p.txt文件中。

esProc SPL脚本如下:


A 注释
1 =file("e:/txt/order_2018.txt").import@t(CustomerId,ProductId) 读出2018订单表中的关键列数据
2 =file("e:/txt/order_2019.txt").import@t(CustomerId,ProductId) 读出2019订单表中的关键列数据
3 =[A1,A2].merge@io() 对两年数据进行归并,@i表示返回共同包含的记录
4 =file("e:/txt/c_p.txt").export@t(A3) A3中的结果写入c_p.txt

c_p.txt文件中部分数据如下:

CustomerId     ProductId
20108     1
20806     3

 

1.2.2.  找不同

示例1:找出2019年新增客户的订单情况,保存在文件new_c.txt中, esProc SPL脚本如下:


A 注释
1 =file("e:/txt/order_2018.txt").import@t() 读出2018年的订单表
2 =file("e:/txt/order_2019.txt").import@t() 读出2019年的订单表
3 =A2.id(CustomerId)\A1.id(CustomerId) 2019年所有客户Id减去2018年的,得到新增的客户Id
4 =A2.select(A3.contain(CustomerId)) 2019年订单表筛选出新增客户的订单
5 =file("e:/txt/new_c.txt").export@t(A4) 将新增客户订单写入文件new_c.txt

new_c.txt中部分数据如下:

..

 

示例2:找出2019年所有流失的客户Id,保存在文件lost_c.txt中, esProc SPL脚本如下:


A 注释
1 =file("e:/txt/order_2018.txt").import@t() 读出2018年的订单表
2 =file("e:/txt/order_2019.txt").import@t() 读出2019年的订单表
3 =A1.id(CustomerId)\A2.id(CustomerId) 2018年所有客户Id减去2019年的,得到流失的客户Id
4 =file("e:/txt/lost_c.txt").write(A3) 将流失客户Id写入文件lost_c.txt

 

2.  大文件比对

大文件数据不能一次性全部装进内存,不能象小文件数据那样全部读出来再进行比对,需要分批读出数据去比较。esProc SPL提供了游标来处理大文件运算,使大文件比对运算也变得十分方便。

2.1  整行比对

有两个大文本文件,其每一行是一个字符串,要对这两个文件中整行内容进行比对。处理此问题要把文件的每一行读成一个字符串,成为游标中的一条记录,然后通过两个游标的运算得出结果。

现有各州房产产权人员登记表大文件,里面记录产权人的身份证及姓名,部分数据如下所示:

    510121198802213364-Joan
    110113199203259852-Jack
    201264197206271113-Mike

2.1.1.   找相同

把两个文件中整行内容相同的行都找出来,即求两文件的交集。

示例:请找出在WashingtonNew York两个州都有房产的人员,记录在w_n.txt文件中。

esProc SPL脚本如下:


A 注释
1 =file("e:/txt/washington.txt").cursor@s().sortx(_1) 创建Washington数据游标,并排序
2 =file("e:/txt/newyork.txt").cursor@s().sortx(_1) 创建New York的数据游标,并排序
3 =[A1,A2].mergex@i() 对两游标数据进行有序归并,@i表示算出共同包含的数据,即在两州都有房产的人员
4 =file("e:/txt/w_n.txt").export(A3) 将算出的结果写入文件w_n.txt

【注】:若文件中的数据是排好序的,则不再调用sortx函数,以下同

 

2.1.2.  找不同

示例:现有全国房产产权人员总表all.txtWashington房产产权人员登记表,请检查总表中是否有遗漏的Washington人员,结果记录在lost_w.txt中。

esProc SPL脚本如下:


A 注释
1 =file("e:/txt/washington.txt").cursor@s().sortx(_1) 创建Washington数据游标,并排序
2 =file("e:/txt/all.txt").cursor@s().sortx(_1) 创建全国的数据游标,并排序
3 =[A1,A2].mergex@d() 对两游标数据进行有序归并,@d表示从A1中去掉A2中的所有人员,即总表中遗漏的Washington人员
4 =file("e:/txt/lost_w.txt").export(A3) 将算出的结果写入文件lost_w.txt

 

2.2  关键列比对

与小文件比对不同,大文件进行关键列比对时要用游标来操作,先按关键列排序,再对两个游标数据进行有序归并计算出需要的结果。

本节仍用小文件比对时的20182019年的销售订单表order_2018.txtorder_2019.txt,只是数据量大大增加到大文件的规模。

2.2.1.  找相同

把两个文件中关键列值相同的都找出来。

示例:请找出这两年都购买了同一种产品的用户CustomerId和产品ProductId,记录在c_p.txt文件中。

esProc SPL脚本如下:


A 注释
1 =file("e:/txt/order_2018.txt").cursor@t(CustomerId,ProductId) 创建2018订单表关键列数据游标
2 =file("e:/txt/order_2019.txt").cursor@t(CustomerId,ProductId) 创建2019订单表关键列数据游标
3 =A1.sortx(CustomerId,ProductId) 2018数据按关键列排序
4 =A2.sortx(CustomerId,ProductId) 2019数据按关键列排序
5 =[A3,A4].merge@i() 对两年数据进行归并,@i表示返回共同包含的记录
6 =file("e:/txt/c_p.txt").export@t(A5) A5中的结果写入c_p.txt

 

2.2.2.  找不同

示例1:找出2019年新增客户的订单情况,保存在文件new_c.txt中, esProc SPL脚本如下:


A 注释
1 =file("e:/txt/order_2018.txt").cursor@t() 创建2018年订单表游标
2 =file("e:/txt/order_2019.txt").cursor@t() 创建2019年订单表游标
3 =A1.groupx(CustomerId) CustomerId分组取得2018客户Id
4 =A2.groupx(CustomerId) CustomerId分组取得2019客户Id
5 =[A4,A3].mergex@d() 2019减去2018,得到新增客户Id
6 =A2.reset().sortx(CustomerId) 2019游标复位后按CustomerId排序
7 =joinx(A6:new_order,CustomerId;A5:new_c,CustomerId) 2019年订单表与新增客户Id连接,筛选出新增客户的订单
8 =file("e:/txt/new_c.txt").export@t(A7.(new_order)) 将新增客户订单写入文件new_c.txt

注:groupx的结果已经按分组字段CustomerId排序。

 

示例2:找出2019年所有流失的客户Id,保存在文件lost_c.txt中, esProc SPL脚本如下:


A 注释
1 =file("e:/txt/order_2018.txt").cursor@t() 创建2018年订单表游标
2 =file("e:/txt/order_2019.txt").cursor@t() 创建2019年订单表游标
3 =A1.groupx(CustomerId) CustomerId分组取得2018客户Id
4 =A2.groupx(CustomerId) CustomerId分组取得2019客户Id
5 =[A3,A4].mergex@d() 2018减去2019,得到流失客户Id
6 =file("e:/txt/lost_c.txt").export@t(A5) 将流失客户Id写入文件lost_c.txt

 

3.  大文件与小文件比对

大文件与小文件对比时,可以把小文件数据全部读进内存,大文件用游标处理,与小文件的数据进行连接计算。

3.1  整行比对

还用上小节的例子,大文件是各州房产产权人员登记表,小文件是某城市房产产权人员登记表。

3.1.1.  找相同

把两个文件中整行内容相同的行都找出来,即求两文件的交集。

示例:请找出在Washington州和New York城都有房产的人员,记录在w_n.txt文件中。

esProc SPL脚本如下:


A 注释
1 =file("e:/txt/washington.txt").cursor@s() 创建Washington数据游标,无需排序
2 =file("e:/txt/newyorkcity.txt").read@n() 读出New York城的数据,@n表示读出整行构成序列
3 =A1.join@i(_1,A2) A1游标数据与A2连接,@i表示只保留A2中有的数据
4 =file("e:/txt/w_n.txt").export(A3) 将算出的结果写入文件w_n.txt

 

3.1.2.  找不同

示例:请检查New York州登记表中是否有遗漏的New York城的人员,结果记录在lost_w.txt中。

esProc SPL脚本如下:


A 注释
1 =file("e:/txt/newyork.txt").cursor@s() 创建Washington数据游标,无需排序
2 =file("e:/txt/newyorkcity.txt").read@n() 读出New York城的数据,@n表示读出整行构成序列
3 =A1.join@i(_1,A2) A1游标数据与A2连接,@i表示只保留A2中有的数据
4 =A2\A3.(_1) A2中减去共有的数据行,得到遗漏的数据行
5 =file("e:/txt/lost_w.txt").export(A4) 将算出的结果写入文件lost_w.txt

 

3.2  关键列比对

本节使用2019年的销售订单表order_2019.txt2019年之前所有年份的订单表order_old.txt,前者是小文件,后者是大文件。

3.2.1.  找相同

示例:请找出2019年及之前某年都购买了同一种产品的用户CustomerId和产品ProductId,记录在c_p.txt文件中。

esProc SPL脚本如下:


A 注释
1 =file("e:/txt/order_old.txt").cursor@t(CustomerId,ProductId) 创建2019之前订单表关键列数据游标
2 =file("e:/txt/order_2019.txt") 读出2019订单表关键列数据
3 =A2.group@1(CustomerId,ProductId) 2019数据删除重复记录
4 =A1.join@i(CustomerId:ProductId,A3:CustomerId:ProductId) A1游标与A3按关键列连接,@i表示只保留能找到的记录
5 =A4.fetch().group@1(CustomerId,ProductId) 取出连接后的结果并删除重复记录
6 =file("e:/txt/c_p.txt").export@t(A5) A5中的结果写入c_p.txt

 

3.2.2.  找不同

示例1:找出2019年新增客户的订单情况,保存在文件new_c.txt中, esProc SPL脚本如下:


A 注释
1 =file("e:/txt/order_old.txt").cursor@t() 创建2019之前订单表数据游标
2 =file("e:/txt/order_2019.txt").import@t() 读出2019订单表数据
3 =A1.groupx(CustomerId) CustomerId分组取得2019之前客户Id
4 =A2.id(CustomerId) 取得2019年所有不重复的客户Id
5 =A3.join@i(CustomerId,A4).fetch() A3A4连接,@i表示保留A4中包含的客户Id
6 =A4\A5.(CustomerId) 2019年客户Id减去A5中的,得到新增的
7 =A2.select(A6.contain(CustomerId)) 筛选出2019新增客户的订单
8 =file("e:/txt/new_c.txt").export@t(A7) 将新增客户订单写入文件new_c.txt

 

示例2:找出2019年所有流失的客户Id,保存在文件lost_c.txt中, esProc SPL脚本如下:


A 注释
1 =file("e:/txt/order_old.txt").cursor@t(CustomerId) 创建2019之前订单表中客户Id游标
2 =file("e:/txt/order_2019.txt").import@t(CustomerId) 读出2019订单表客户Id数据
3 =A2.id(CustomerId) 取得2019中不重复的客户Id
4 =A1.select(!A3.contain(CustomerId)) 2019之前的客户中筛选出不在2019年的
5 =A4.groupx(CustomerId) Id删除重复的客户
6 =file("e:/txt/lost_c.txt").export@t(A5) 将流失客户订单写入文件lost_c.txt

 

 

》,中有更多相关计算示例。

 


阅读(1522) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~