2013-03-09 42 views
1

我有一個CSV文件,其中一個是許多CSV文件。這樣的事情:使用Scala將文本文件解析爲組

"First Part" 
"Some", "data", "in", "here" 
"More", "stuff", "over", "here" 

"Another Part" 
"This", "section", "is", "not", "the", "same", "as", "the", "first" 
"blah", "blah", "blah", "blah", "blah", "blah", "blah", "blah", "blah" 

"Yet another section" 
"And", "this", "is", "yet", "another" 
"blah", "blah", "blah", "blah", "blah" 

我想分解成單獨的組件。鑑於我知道每個部分的標題,如果我可以做某種類型的groupBy或者其中我傳遞了一組代表標題模式的正則表達式並返回Seq[Seq[String]]或類似內容,那就會很好。

+0

可能有很多因素需要考慮。你需要處理大文件還是可以將所有內容加載到內存中?你需要處理轉義的CSV字符嗎?你關心表現還是你需要一些簡單的東西? – huynhjl 2013-03-09 17:54:27

+0

這是一個小文件......最大100K,所以我打算把所有東西都放到記憶裏 – andyczerwonka 2013-03-09 20:46:08

回答

1

你可以做到以下幾點:

val groups = List("\"First Part\"", "\"Another Part\"", "\"Yet another section\"") 
val accumulator = List[List[String]]() 
val result = input.split("\n").foldLeft(accumulator)((acc,e) => { 
    if (groups.contains(e)) { 
    // Make new group when we encounter a string matching one of the groups 
    Nil :: acc 
    } else { 
    // Grab current group and modify it 
    val newHead = e :: acc.head 
    newHead :: acc.tail 
    } 
}) 

result每個列表現在代表一個組。如果你想使用正則表達式找到你的匹配,那麼只需用匹配測試替換groups.contains(e)。這裏有一些細微之處,可能值得一提:

  • 如果輸入不帶標題
  • 如果標題出現幾次它存在會產生一個新的組,每次啓動該算法將失敗
  • 組將在輸入中反向包含行。
  • 空行也將包含在結果中。
0

編輯這是類似於同時發佈的其他解決方案。部分標題可以做類似的事情,而不是我的快速破解大小== 1。此解決方案還具有包含secion名稱的額外好處,因此排序無關緊要。

val file: List[String] = """ 

heading 
1,2,3 
4,5 

heading2 
5,6 
""".split("\n").toList 
val splitFile = file 
    .map(_.split(",").toList) 
    .filterNot(_ == List("")) 
    .foldLeft(List[(String, List[List[String]])]()){ 
    case (h::t,l) => {if(l.size==1) (l(0),List()):: h :: t else (h._1, l :: h._2) :: t}; 
    case (Nil, l)=> if(l.size==1) List((l(0),List())) else List() } 
    .reverse 

產生

splitFile: List[(String, List[List[String]])] = List((heading,List(List(4, 5), List(1, 2, 3))), (heading2,List(List(5, 6))))