java - 使用 Groovy 重新映射 CSV 结构
问题描述
我尝试创建一些脚本,但一切看起来都太长、太麻烦而且效率很低。你能分享一个如何最有效地做到这一点的想法吗?
案例描述:
- 三个输入文件(管道分隔)
- 每个文件都有不同的标题,但其中许多字段是通用的 = 它们具有相同的字段名称
- 我创建了一个通用标题。即,标题组合所有三个文件的字段。
- 数据中不存在标头,但存储在变量中,例如 String Header1 = "XXX"
下面是一个示例结构:
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'”)这些属性只包含字符串中的值。在代码中,我检查他们发送的数据是否有效——例如字段计数是否与标题相同,从标题中删除重复字段,然后进行一些额外的检查。
解决方案
问题是关于根据通用标题映射值。
我没有介绍在哪里存储所有这些标头以及如何为传入文件找到正确的标头。
所以,这里只是一个简单的映射
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()
推荐阅读
- javascript - 如何接收上传图片的 URL 并将其传递给 CK Editor 中的“src”属性?
- java - 为什么 sensorManager.registerListener 无法为 Step Counter 注册监听器?
- hive - 如何更新 Hive 表行
- php - 如何使用 html 和 php 自动填充以前上传的文件?
- html - 引导文本在 iOS 上的输入中不可见
- json - 如何正确使用 HttpPatch 和 JsonPatchDocument
- java - 没有修饰符(默认)的类不能访问声明为公共的子类?爪哇
- python - Django,带有非ascii文本的csv文件在windows excel文件中不可读
- javascript - 在Javascript中查找水平滚动条的拇指宽度
- java - 新计算机上 DDE 中的 Java 编译器错误,在旧计算机上运行良好