使用Scala将文本文件解析为组

时间:2013-03-09 02:59:49

标签: parsing scala

我有一个CSV文件,它实际上是一组许多CSV文件。像这样:

"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]]或类似的东西,那就太好了。

2 个答案:

答案 0 :(得分: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)即可。这里有一些细微之处值得一提:

  • 如果输入未以标题
  • 开头,则算法将失败
  • 如果每次出现标题多次,则会生成一个新组
  • 组将反向包含输入中的行。
  • 结果中还会包含空行。

答案 1 :(得分: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))))