2013-04-24 23 views
0

我有一個tsv文件的形式是「key \ t值」,我需要讀入地圖。目前我這樣做:更方便的解析tsv文件到地圖

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

有沒有更簡單/更好的方法來做到這一點?

+0

IMO,這是一個「代碼高爾夫」問題。這段代碼很像Groovy。可能有辦法做到這一點更聰明,但不是「更好」。 – 2013-04-25 07:20:09

+0

@MichaelEaster我不同意 - 我認爲試圖找到更好的方法來做一個重複的任務是一種很好的方式來提高你的語言知識 – Yossale 2013-04-25 08:03:25

+0

一般來說,這是真的,但在這種情況下,它是很難找到更好的東西。你的時間在別處度過的更好。 – 2013-04-25 08:07:25

回答

1

我能想到這樣做的唯一的另一個方法是先用一個Iterator像你在下議院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 

因爲它涉及引用的字符串

4

它已經很短了。兩個答案我能想到的:

首先一個避免了臨時地圖對象的創建:

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 } 
+5

或'referenceFile.collect {it.tokenize('\ t')} .collectEntries {k,v - > [k.toLowerCase(),v]};;} – 2013-04-24 13:00:45

1

這是評論tim_yates加入melix的答案,我認爲這是最短/最清晰的答案:

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

真的,這是最短的一個,但所有答案除外對於CSV解析器,下面的一個不會處理帶引號的引用值或鍵(請參閱我的答案中的註釋),因此無論是「最佳」_取決於您最佳的定義;-) – 2013-04-25 08:15:16