免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 7847 | 回复: 16
打印 上一主题 下一主题

[数值计算] 比较两个文件里的某个列 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-04-04 21:06 |只看该作者 |倒序浏览
要比较两个文件的某个列的值大小,内容如下:
A.lst:
a,8
b,3
c,5
d,6

B.lst:
b,4
d,6
a,5

第一列是key,第二列是value。
B.lst 的key 是 A.lst 的key的子集。两个文件的行都是乱序的。
要求比较同一个key在两个文件里的value的大小,并把A.value > B.value 的key打印出来输出到result.lst,结果和格式如下:
result.lst:
a A:8 B:5
c A:5 B:
(输出的行序没要求,当key在A.lst有而B.lst没有时,也打印出来,如c)

题目看上去很简单,不过我发现实现的方法有很多,效率差别也很大。当文件的行数达到上万行时,执行时间会有几百倍的差别。

欢迎大家提出自己的方法和见解,我在网上找过但没找到合适的。稍后我也会给出自己的方法。

论坛徽章:
32
处女座
日期:2013-11-20 23:41:20双子座
日期:2014-06-11 17:20:43戌狗
日期:2014-06-16 11:05:00处女座
日期:2014-07-22 17:30:47狮子座
日期:2014-07-28 15:38:17金牛座
日期:2014-08-05 16:34:01亥猪
日期:2014-08-18 13:34:25白羊座
日期:2014-09-02 15:03:55金牛座
日期:2014-11-10 10:23:58处女座
日期:2014-12-02 09:17:52程序设计版块每日发帖之星
日期:2015-06-16 22:20:002015亚冠之塔什干火车头
日期:2015-06-20 23:28:22
2 [报告]
发表于 2014-04-04 22:11 |只看该作者
  1. $ awk -F, 'FNR==1{a[ARGIND]=gensub(/^(.*)\.lst$/,"\\1",1,FILENAME)}NR==FNR{b[$1]=$2;next}$2>b[$1]{printf "%s %s:%s %s:%s\n",$1,a[2],$2,a[1],b[$1]}' B.lst A.lst
  2. a A:8 B:5
  3. c A:5 B:
复制代码

论坛徽章:
0
3 [报告]
发表于 2014-04-04 22:49 |只看该作者
回复 2# yestreenstars

好厉害的awk啊!学习了!{:3_198:}

论坛徽章:
0
4 [报告]
发表于 2014-04-04 22:54 |只看该作者
刚才无意中挖出join这个工具,也拿来练练手吧,不过join要先排序才行。
  1. sort A.lst > A.sort
  2. sort B.lst > B.sort
  3. join -a1 -t"," -1 1 -2 1 A.sort B.sort |awk -F, '$2>$3 {print $1 " A:"$2" B:" $3}'
  4. rm A.sort B.sort
复制代码

论坛徽章:
0
5 [报告]
发表于 2014-04-05 00:49 |只看该作者
本帖最后由 badcow 于 2014-04-05 00:53 编辑

2楼 yestreenstars 的方法简直是豪鬼的瞬狱杀啊,跑1万多行的文件只需0.062秒,真是“毫秒杀”啊!

我再把自己之前用“关联数组”的土办法贴出来,这个要bash 4.0以上才支持。
  1. #!/bin/bash

  2. declare -A A
  3. declare -A B

  4. awk -F, '{print "A["$1"]""="$2}' A.lst > A.lst.tmp
  5. . A.lst.tmp && rm A.lst.tmp

  6. awk -F, '{print "B["$1"]""="$2}' B.lst > B.lst.tmp
  7. . B.lst.tmp && rm B.lst.tmp

  8. for I in ${!A[*]}
  9. do
  10. if [[ "${A[$I]}" -gt "${B[$I]}" ]]; then
  11.   printf "%s A:%s B:%s\n" $I ${A[$I]} ${B[$I]}
  12. fi
  13. done
复制代码
本来想用循环给数组赋值的,但是循环一结束,那个数组的值就变空了,不知道为什么,希望高人指点。所以迫不得已用点执行tmp文件来给数组赋值。
用这个方法跑1万行文件,结果秒出(0.8秒),但比起yestreenstars 的毫秒出,还是太差了,呵呵,佩服佩服!

PS. 最初我居然用read + grep 的方法,耗时要几分钟,就没必要再拿出来丢人了,哈哈哈!

论坛徽章:
93
2015年辞旧岁徽章
日期:2019-10-10 10:51:15CU大牛徽章
日期:2014-02-21 14:21:56CU十二周年纪念徽章
日期:2020-10-15 16:55:55CU大牛徽章
日期:2014-02-21 14:22:07羊年新春福章
日期:2019-10-10 10:51:39CU大牛徽章
日期:2019-10-10 10:55:38季节之章:春
日期:2020-10-15 16:57:40ChinaUnix元老
日期:2019-10-10 10:54:42季节之章:冬
日期:2019-10-10 10:57:17CU大牛徽章
日期:2014-02-21 14:22:52CU大牛徽章
日期:2014-03-13 10:40:30CU大牛徽章
日期:2014-02-21 14:23:15
6 [报告]
发表于 2014-04-08 13:08 |只看该作者
回复 5# badcow


    循环给数组赋值的那个问题没把代码贴出来,估计是大家都有问过的子进程的问题。用了管道读文件了是吗?是的话八成是子进程的问题了。

论坛徽章:
11
金牛座
日期:2015-03-19 16:56:22数据库技术版块每日发帖之星
日期:2016-08-02 06:20:00数据库技术版块每日发帖之星
日期:2016-04-24 06:20:00数据库技术版块每日发帖之星
日期:2016-04-13 06:20:00IT运维版块每日发帖之星
日期:2016-04-13 06:20:00数据库技术版块每日发帖之星
日期:2016-02-03 06:20:00数据库技术版块每日发帖之星
日期:2015-08-06 06:20:00季节之章:春
日期:2015-03-27 15:54:57羊年新春福章
日期:2015-03-27 15:54:37戌狗
日期:2015-03-19 16:56:41数据库技术版块每日发帖之星
日期:2016-08-18 06:20:00
7 [报告]
发表于 2014-04-08 14:46 |只看该作者
本帖最后由 liaosnet 于 2014-04-08 14:50 编辑

这个用AWK很简单吧。。

  1. awk -F',' 'NR==FNR{b[$1]=$2}NR>FNR{a[$1]=$2;if(a[$1]>b[$1])print $1,"A:"a[$1],"B:"b[$1]}' B.lst A.lst
复制代码

论坛徽章:
3
水瓶座
日期:2014-02-20 12:02:14天蝎座
日期:2014-03-19 14:04:46水瓶座
日期:2014-07-26 20:01:02
8 [报告]
发表于 2014-04-08 15:43 |只看该作者
awk 'BEGIN{FS=",";OFS=" "} FNR==NR{a[$1]=$2;next}!a[$1]{print $1 OFS "A:" $2 OFS "B:";next}a[$1]{if($2>a[$1]) print $1 OFS "A:" $2 OFS "B:" a[$1]}' B.lst A.lst

论坛徽章:
0
9 [报告]
发表于 2014-04-09 09:56 |只看该作者
本帖最后由 yaozhibing41001 于 2014-04-09 09:57 编辑

回复 1# badcow

python来一发
  1. #! /usr/bin/python

  2. _file_A=open('C:\Users\Administrator\Desktop\python\A.lst','r')
  3. _file_B=open('C:\Users\Administrator\Desktop\python\B.lst','r')


  4. _L_A=_file_A.read().split("\n")
  5. _List_A=','.join(_L_A).split(",")
  6. _Data_A=dict(zip(_List_A[0::2],_List_A[1::2]))

  7. _L_B=_file_B.read().split("\n")
  8. _List_B=','.join(_L_B).split(",")
  9. _Data_B=dict(zip(_List_B[0::2],_List_B[1::2]))



  10. for value in _Data_A:
  11.     if _Data_B.has_key(value) and  _Data_A[value] > _Data_B[value]:
  12.          print value,"A:",_Data_A[value],"B:",_Data_B[value]
  13.     elif _Data_B.has_key(value)==False:
  14.          print value,"A:",_Data_A[value],"B:"
  15. _file_A.close()
  16. _file_B.close()
复制代码

论坛徽章:
0
10 [报告]
发表于 2014-04-09 16:43 |只看该作者
回复 6# seesea2517

我猜也是子进程问题,即使用awk的system来跑也会是变空:
  1. declare -A A
  2. awk -F, '{system("A["$1"]""="$2)}'  A.lst
  3. echo ${A[*]}
复制代码
这样跑的话,数组A最后也是变空。

   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP