【问题标题】:comparing 2 large unsorted CSV files based on 2 columns基于 2 列比较 2 个未排序的大型 CSV 文件
【发布时间】:2011-10-23 09:41:43
【问题描述】:

我的任务是根据第 1 列和第 3 列比较 2 个未排序的大型 .csv 文件。 每个文件包含大约 200k 条记录。对于输出,我需要知道基于第 1 列和第 3 列的哪些记录存在于第一个文件中,而不是第二个文件中。这些文件是引用的逗号分隔值文件。第 3 列在比较时需要忽略大小写。

示例文件1:

"id", "name", "email", "country"
"1233",  "jake", "jake@mailinator.com", "USA"
"2345", "alison", "Alison@mailinator.com", "Canada"
"3456", "jacob", "jacob@mailinator.com", "USA"
"5678", "natalia", "natalia@mailinator.com", "USA"

文件 2

"id", "name", "email", "country"
"2345", "alison", "alison@mailinator.com", "Canada"
"3456", "jacob", "jacob@mailinator.com", "USA"
"5690", "lina", "lina@mailinator.com", "Canada" 

所需的输出文件

"5678", "natalia", "natalia@mailinator.com", "USA"

非常感谢代码示例。

【问题讨论】:

  • 到目前为止你做了什么语言和什么,有什么问题?
  • 为什么输出中没有出现"1233", "jake", "jake@mailinator.com", "USA"这一行?
  • 嗨,马克,我用 HashMaps 尝试了 java,但速度非常慢。
  • brandizzi,你是对的,杰克应该出现

标签: java python shell csv awk


【解决方案1】:

试试:

join -v 1 -i -t, -1 1 -2 1 -o 1.2 1.3 1.4 1.5  <(awk -F, '{print $1":"$3","$0}' f1.txt | sort) <(awk -F, '{print $1":"$3","$0}' f2.txt | sort)

它是如何工作的:

1) 我首先通过连接第 1 列和第 3 列来创建一个复合键列:

awk -F, '{print $1":"$3","$0}' f1.txt
awk -F, '{print $1":"$3","$0}' f2.txt

2) 我对两个输出进行排序:

awk -F, '{print $1":"$3","$0}' f1.txt | sort 
awk -F, '{print $1":"$3","$0}' f2.txt | sort 

3) 然后我使用join 命令加入第一列(我的复合键)并输出来自文件 1 的不可配对行。

输出:

"1233",  "jake", "jake@mailinator.com", "USA"
"5678", "natalia", "natalia@mailinator.com", "USA"

【讨论】:

  • +1 第 3 列应该不区分大小写,所以只需要 tolower($3) 代替。
  • awk 命令像一个魅力,但是 join 抱怨,1) 它说 -i 不是一个有效的选项使用:GNU bash,版本 3.2.48(1)-release (x86_64-apple -darwin10.0) 版权所有 (C) 2007 Free Software Foundation, Inc.
【解决方案2】:

循环文件,将它们加载到 2 个数组(或者可能是哈希)中,然后循环第二个文件,对每一行进行数组化。如果array1[n]array2[n] 不在当前行的数组中,则输出为缺失。我会使用 Perl 来完成这项任务。

【讨论】:

  • 文件很大。将它们加载到数组中可能不明智。
  • 然后对于基础文件中的每一行,在第二个文件中逐行搜索。没那么快,但你不会遇到内存问题。
【解决方案3】:
awk 'BEGIN { FS="\", \""}
     FNR == 1 {read++;}
     FNR !=1 {if (read==1) {store[$1","tolower($3)] = $0} if (read==2) {delete store[$1","tolower($3)]}}
     END {for (i in store) {print store[i]}}' file1 file2

输出:

"1233",  "jake", "jake@mailinator.com", "USA"
"5678", "natalia", "natalia@mailinator.com", "USA"

【讨论】:

    【解决方案4】:

    将文件内容加载到内存数据库中,例如H2 并使用带有连接的 SQL 选择

    【讨论】:

      【解决方案5】:
      awk 'BEGIN { FS=OFS=","}; NR==FNR{a[tolower($1$3)]=++i;next} { if ( tolower($1$3) in a);else {print } }' file2 file1
      

      输出:

      "1233",  "jake", "jake@mailinator.com", "USA"
      "5678", "natalia", "natalia@mailinator.com", "USA"
      

      【讨论】:

        猜你喜欢
        • 2018-10-23
        • 1970-01-01
        • 2019-01-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多