我有一个文本行列表,并希望将任何以'\'结尾的行视为继续到下一行,即合并它们。下面的递归代码可以实现,但必须有一些聪明的方法,类似于map
,filter
和所有?
reduceLeft
已关闭,但它只生成一个结果,而不是修改后的(可能更短的)新列表。
此外,欢迎提供以下代码以使代码更精简的建议。
object TestX extends App {
// Merge lines together if the former ends with '\'.
//
private def mergeLines( list: List[String] ): List[String] = {
def merge( head: String, tail: List[String] ): List[String] = {
if (head.endsWith("\\")) {
val head2= head.dropRight(1)
if (tail.isEmpty) {
head2 :: Nil // or throw an exception on bad input
} else {
merge( head2 + tail.head, tail.tail )
}
} else {
if (tail.isEmpty)
head :: Nil
else
head :: merge( tail.head, tail.tail ) // note: cannot tailrec this
}
}
if (list.isEmpty) {
list
} else {
merge( list.head, list.tail )
}
}
val list = "These two \\" :: "should be joined" :: "but not this." :: Nil
val list2 = mergeLines(list) // any standard easy way to do this? 'list.mergeIf( _.endsWith('\\') )'
println( list2 )
assert( list2.size == 2 )
}
答案 0 :(得分:0)
您可以使用foldLeft:
编写它List("a\\", "b", "c").foldLeft(List.empty[String])((xs, x) => xs match {
case Nil => x :: Nil
case _ => if (xs.head.endsWith("\\")) (xs.head.dropRight(1) + x) :: xs.tail else x :: xs
}).reverse
它可能不是最有效的方式(适用于小型列表,但不适用于大型列表),因为它使用不可变数据结构,更有效的方法是使用可变列表。
答案 1 :(得分:0)
以下是一些可以使用的技巧:
@annotation.tailrec
def mergeLines(xs: List[String], out: List[String] = Nil): List[String] = xs match {
case Nil => out.reverse
case x :: Nil => mergeLines(Nil, x :: out)
case x :: y :: rest =>
if (x endsWith """\""") mergeLines(x.init + y :: rest, out)
else mergeLines(y :: rest, x :: out)
}