Groovy 将tsv文件解析为映射的Groovier方法

Groovy 将tsv文件解析为映射的Groovier方法,groovy,Groovy,我有一个“key\t value”形式的tsv文件,需要读入地图。目前我是这样做的: referenceFile.eachLine { line -> def (name, reference) = line.split(/\t/) referencesMap[name.toLowerCase()] = reference } 有没有更短/更好的方法 我能想到的唯一其他方法是使用迭代器,就像您在Commons IO中看到的那样: @Grab( 'commons-io:co

我有一个“key\t value”形式的tsv文件,需要读入地图。目前我是这样做的:

referenceFile.eachLine { line ->
    def (name, reference) = line.split(/\t/)
    referencesMap[name.toLowerCase()] = reference
}

有没有更短/更好的方法

我能想到的唯一其他方法是使用迭代器,就像您在Commons IO中看到的那样:

@Grab( 'commons-io:commons-io:2.4' )
import org.apache.commons.io.FileUtils

referencesMap = FileUtils.lineIterator( referenceFile, 'UTF-8' )
                         .collectEntries { line ->
  line.tokenize( '\t' ).with { k, v ->
    [ (k.toLowerCase()): v ]
  }
}
或使用CSV解析器:

@Grab('com.xlson.groovycsv:groovycsv:1.0')
import static com.xlson.groovycsv.CsvParser.parseCsv

referencesMap = referenceFile.withReader { r ->
  parseCsv( [ separator:'\t', readFirstLine:true ], r ).collectEntries {
    [ (it[ 0 ].toLowerCase()): it[ 1 ] ]
  }
}
但它们都不短,也不一定更好

尽管我更喜欢选项2,因为它可以处理以下情况:

"key\twith\ttabs"\tvalue

由于它处理带引号的字符串

我能想到的唯一其他方法是使用迭代器,就像您在Commons IO中看到的那样:

@Grab( 'commons-io:commons-io:2.4' )
import org.apache.commons.io.FileUtils

referencesMap = FileUtils.lineIterator( referenceFile, 'UTF-8' )
                         .collectEntries { line ->
  line.tokenize( '\t' ).with { k, v ->
    [ (k.toLowerCase()): v ]
  }
}
或使用CSV解析器:

@Grab('com.xlson.groovycsv:groovycsv:1.0')
import static com.xlson.groovycsv.CsvParser.parseCsv

referencesMap = referenceFile.withReader { r ->
  parseCsv( [ separator:'\t', readFirstLine:true ], r ).collectEntries {
    [ (it[ 0 ].toLowerCase()): it[ 1 ] ]
  }
}
但它们都不短,也不一定更好

尽管我更喜欢选项2,因为它可以处理以下情况:

"key\twith\ttabs"\tvalue

因为它处理的是带引号的字符串

,所以它已经很短了。我能想到两个答案:

第一种方法避免创建临时贴图对象:

referenceFile.inject([:]) { map, line ->
    def (name, reference) = line.split(/\t/)
    map[name.toLowerCase()] = reference
    map
}
第二个更具功能性:

referenceFile.collect { it.split(/\t/) }.inject([:]) { map, val -> map[val[0].toLowerCase()] = val[1]; map }

已经很短了。我能想到两个答案:

第一种方法避免创建临时贴图对象:

referenceFile.inject([:]) { map, line ->
    def (name, reference) = line.split(/\t/)
    map[name.toLowerCase()] = reference
    map
}
第二个更具功能性:

referenceFile.collect { it.split(/\t/) }.inject([:]) { map, val -> map[val[0].toLowerCase()] = val[1]; map }

这是tim_yates在melix的答案中添加的评论,我认为这是最短/最清晰的答案:

referenceFile.collect { it.tokenize( '\t' ) }.collectEntries { k, v -> [ k.toLowerCase(), v ] }

这是tim_yates在melix的答案中添加的评论,我认为这是最短/最清晰的答案:

referenceFile.collect { it.tokenize( '\t' ) }.collectEntries { k, v -> [ k.toLowerCase(), v ] }

referenceFile.collect{it.tokenize('\t')}.collectEntries{k,v->[k.toLowerCase(),v]}
;-)或
referenceFile.collect{it.tokenize('\t')}.collectEntries{k,v->[k.toLowerCase(),v]}
;-)在国际海事组织,这是一个“规范高尔夫”问题。这段代码是非常Groovy的。也许有更聪明的方法,但不是“更好的”。@MichaelEaster我不同意——我认为尝试找到更好的方法来完成一项重复的任务是提高你的语言知识的一个好方法。总的来说,这是真的,但在这种情况下,很难找到更好的方法。你最好把时间花在别处。依我看,这是一个“代码高尔夫”的问题。这段代码是非常Groovy的。也许有更聪明的方法,但不是“更好的”。@MichaelEaster我不同意——我认为尝试找到更好的方法来完成一项重复的任务是提高你的语言知识的一个好方法。总的来说,这是真的,但在这种情况下,很难找到更好的方法。您的时间最好花在其他地方。没错,这是最短的答案,但除下面的CSV解析器外,所有答案都不会处理带引号的值或带有制表符的键(请参见我答案中的注释),因此它是否“最佳”取决于您对最佳的定义;-)没错,这是最短的答案,但是除了下面的CSV解析器外,所有答案都不会处理带引号的值或带制表符的键(请参见我答案中的注释),因此它是否“最佳”取决于您对“最佳”的定义;-)