在groovy中比较两个csv文件

mf98qq94  于 2023-03-07  发布在  其他
关注(0)|答案(2)|浏览(154)

我正在尝试创建一个比较脚本来比较两个SQL表。这两个表中的每一个都有大约4.000行。
我使用Groovy导入表并将其存储为CSV文件,对于两个CSV,第一列是需要用于比较的ID。
每个ID号可能有多行。一个CSV中的ID的行数可能与另一个CSV中的相同ID的行数不同。
例如:

CSV1    -     CSV2
---------  -  ----------
ID, Value  -  ID , value
1 , A      -  1  , A
1 , B      -  2  , A
2 , A      -  2  , B
3 , B      -  3  , C

因此,在上面的示例中,我期望输出如下

ID,Value, FoundIn
 1, A   , both
 1, B   , 1
 2, A   , both
 2, B   , 2
 3, B   , 1
 3, B   , 2

到目前为止,我还没有在Groovy中找到进行这种比较的合适方法。
我试过在groovy中嵌套bash并使用diff命令,如下所示:

"println "diff -sw /home/testFolder/file1.txt /home/testFolder/file2.txt".execute().text

但是diff执行逐行比较,在本例中不起作用。
有没有更好的办法?
我的编程知识非常狭窄,我很乐意使用一些帮助。我希望我已经给了你足够的信息来理解这个问题,但如果没有,我很乐意提供更多。
先谢了
编辑:
只是为了弄清楚一点
例如:

CSV1    -     CSV2
---------  -  ----------
ID, value  -  ID , value
1 , A      -  1  , A
1 , B      -  2  , A
2 , A      -  2  , B
3 , B      -  3  , C

上面的例子只显示了两个文件的假定内容,而不是实际结构。因此,我有两个不同的文件。我只是使用连字符(-)来表示它们是不同的文件。文件中没有连字符。我已经有了两个csv文件,它们的内容是从sql表导入的。每个csv文件的内容如下所示:

[id:1, value1:A, value2:B, value3:C]
[id:1, value1:A, value2:G, value3:K]
[id:2, value1:A, value2:G, value3:K]

其中ID、值1、值2、值3
它曾经是SQL表的列名。
所以我有这些csv文件,我需要的是比较他们的内容。

cetgtptt

cetgtptt1#

def csvParser = {String filePath->
    File csvFile = new File("/home/sachin/Projects/scripts/groovyScript/csv.csv")
    def keys = []
    def data = []
    csvFile.eachLine{line, i ->
      if(i==1) {
        keys = line.split(',')
        return
      }
      def map = [:]
      line.split(',').eachWithIndex{val, j-> 
        map[keys[j]] = val
      }
      data.push(map)    
    }
    data
}
def data = ["path1","path2"].collect {csvParser(it)}
def extraInFirst = data[0] - data[1]
def extraInSecond = data[1] - data[0]
def common = (data[0] - (data[0] - data[1]))

预期输入格式:

ID, Value 
1 , A     
1 , B     
2 , A     
3 , B

现在,extraInFirstextraInSecondcommon中的所有必需值都已存在
它检查每个字段的差异。如果任何字段是不同的,那么它将不会是一个共同的一部分。我希望你能从它生成任何输出。

qxsslcnc

qxsslcnc2#

假设文件中没有两行是相同的,我的方法是为每个文本文件创建一个Set of Map,其中每行由一个Map表示,创建的Map是可散列的(但不是Comparable),所以我将使用这个属性来比较它们。

Set<Map> left = parseTextFile("/home/testFolder/file1.txt")
Set<Map> right = parseTextFile("/home/testFolder/file2.txt")

Set<Map> inBoth = left.findAll { it in right }
Set<Map> onlyInLeft = left.findAll { !(it in inBoth) }
Set<Map> onlyInRight = right.findAll { !(it in inBoth) }

Set<Map> parseTextFile(String fileName){
    new File(fileName).collect { String line ->
        line.trim()[1..-2].split(',').collectEntries { it.trim().split(":") }
    }
}

这种方法的运行时间大约为 O(n),其中 n 是较长文件的行数。尽管看起来很棒,但我建议不要在非Comparable对象上使用minus()操作符。时间复杂度将增加到 O(n2),这对于4000行来说是显而易见的。

相关问题