首页 > 解决方案 > 使用 Groovy 重新映射 CSV 结构

问题描述

我尝试创建一些脚本,但一切看起来都太长、太麻烦而且效率很低。你能分享一个如何最有效地做到这一点的想法吗?

案例描述:

下面是一个示例结构:

Header of File 1:
Title|Postcode|Forename|Address2|Surname|Birthday|Address1|Address3|Addres4|
Header of File 2:
Title|Surname|Forename|Address1|Birthday
Header of File 3:
Title|Forename|Surname|Address1|Address2|Postcode|LicencePlate

The generic structure I need individual fields to be remapped to:
Title|Forename|Surname|Address1|Address2|Address3|Address4|Postcode|Birthday|LicencePlate

目标是以通用标头定义的格式输出重新格式化的数据。单个文件中缺少的字段在结果结构中将为空。

我将使用的数据有:文件 1-3 各有大约 800 个字段,通用结构有 1300 个字段,其中大约 450 个字段在所有三个文件中是相同的,其余的对于特定文件是唯一的。

下面的示例数据:

File 1 input:
Mr|AJX 11E|John|Dummy Town|Doe|11/12/1972|15 Dummy Street|Dummy County|Dummy Country|
Mrs|XX A54|Evelin|Test Town|Blond|5/3/2001|3 Test Street|Test County|Test State|

File 1 output: 
Mr|John|Doe|15 Dummy Street|Dummy Town|Dummy County|Dummy Country|AJX 11E|11/12/1972||
Mrs|Evelin|Blond|3 Test Street|Test Town|Test County|Test State|XX A54|5/3/2001||

File 2 input:
Mr|Doe|John|15 Dummy Street|11/12/1972|
Mrs|Blond|Evelin|3 Test Street|5/3/2001|

File 2 output:
Mr|John|Doe|15 Dummy Street|||||11/12/1972||
Mrs|Evelin|Blond|3 Test Street|||||5/3/2001||

File 3 input:
Mr|John|Doe|15 Dummy Street|Dummy Town|AJX 11E|AJX 11E|
Mrs|Evelin|Blond|3 Test Street|Test Town|XX A54|XX A54|

File 3 output:
Mr|John|Doe|15 Dummy Street|Dummy Town|||AJX 11E||AJX 11E|
Mrs|Evelin|Blond|3 Test Street|Test Town|||XX A54||XX A54|

谢谢你的建议

编辑:这是我基于真实数据的代码:dropbox.com和头文件 - dropbox.com。代码使用我们使用的软件的专有属性(例如“job.'descriptor'”)这些属性只包含字符串中的值。在代码中,我检查他们发送的数据是否有效——例如字段计数是否与标题相同,从标题中删除重复字段,然后进行一些额外的检查。

标签: javacsvgroovy

解决方案


问题是关于根据通用标题映射值。

我没有介绍在哪里存储所有这些标头以及如何为传入文件找到正确的标头。

所以,这里只是一个简单的映射

String [] genericHeader = 'Forename|Surname|Title|Address1|Address2|Address3|Address4|Postcode|Birthday|LicencePlate'.split('\\|',-1)

//convert header to a map: name->index for faster access
Map<String,Integer> header = 'Title|Forename|Surname|Address1|Address2|Postcode|LicencePlate'.split('\\|',-1).toList().withIndex().collectEntries()

//mapper - array of indexes: null = empty field, 0+ = index where to take the value
Integer[] mapper = genericHeader.collect{ header[it] }

//could be new File(filename).newReader("UTF-8")
Reader reader = new StringReader('''\
Mr|John|Doe|15 Dummy Street|Dummy Town|AJX 11E|AJX 11E
Mrs|Evelin|Blond|3 Test Street|Test Town|XX A54|XX A54
''')

//could be new File(filename).newWriter("UTF-8")
Writer writer = new StringWriter()

//process reader, remap each line, write it to writer
reader.eachLine{String line->
    String [] row = line.split('\\|',-1)
    writer << mapper.collect{ it==null ? "" :row[it] }.join('|') << '\n'
}

writer.flush()
writer.close()

//print for test
println writer.toString()

推荐阅读