下面是尾遞歸函數,將組指定的方式您的輸入線。
想法很簡單:逐行處理輸入。遇到key->value
對時,將其添加到緩衝區(或累加器)。當行看起來不像k->v
對時,將此行添加到已存在於緩衝區中的最後一對的值字符串中。
val s =
"""k -> v \n
| test
| \n here
|k2 -> v2
""".stripMargin.split("\n").toList
def rec(input:List[String]):Map[String, String] = {
val ARROW = "\\s*(.+?)\\s*->\\s*(.+?)\\s*".r
def r0(in:List[String], accum:List[(String, List[String])]):List[(String, List[String])] = in match {
// end of input, reverse line accumulators
case Nil => accum.map{case (k, lines) => k -> lines.reverse}.reverse
// key -> value line encountered, adding new k->v pair to outer accumulator
case ARROW(k, v) :: tail => r0(tail, (k, List(v)) :: accum)
// line without key encountered, adding this line to previous k->v pair in the accumulator
case line :: tail => r0(tail, accum match {
case (k, lines) :: accTail => (k, line :: lines) :: accTail
case _ => accum // if accum is empty and input doesn't have a key, ignore line
})
}
r0(input, Nil).toMap.mapValues(_.mkString("\n"))
}
rec(s).foreach(println(_))
結果:
(k,v \n
test
\n here)
(k2,v2
)
每一行被處理正好一次,也緩衝區的每個的增加和修改是O(1),所以整個過程是O(N)。
此外,請注意,您正在以保留資源的方式閱讀文件。請參閱to this for details。
你說的值是多行的,那麼'k'的值是多少?是'v'還是'test'或'here'? –