1

我有一个 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或某事,我可以传递一组表示标题模式的正则表达式并返回 aSeq[Seq[String]]或类似的东西。

4

2 回答 2

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)为匹配测试。这里有一些微妙之处可能值得一提:

  • 如果输入不是以标题开头,算法将失败
  • 如果一个标题每次出现多次都会生成一个新组
  • 组将反向包含输入中的行。
  • 结果中也将包含空行。
于 2013-03-09T06:29:02.780 回答
0

编辑这类似于同时发布的其他解决方案。可以对部分标题进行类似的操作,而不是我对 size==1 的快速破解。此解决方案具有包含部分名称的额外好处,因此排序无关紧要。

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))))
于 2013-03-09T06:32:49.753 回答