dmi*_*747 3 functional-programming scala
我们有一个带有BEGIN和END标记的字符串列表作为此列表的一部分.我们可以在函数式编程风格中过滤出BEGIN-END之间的元素吗?我只是在scala中使用这种常规(标记)方法出来了.
val list1 =
"""992
1010
1005
1112
BEGIN
1086
1244
1107
1121
END
1223
1312
1319
1306
1469""".lines.toList
var flag = false
val filteredList = list1.filter{
def f(x: String): Boolean = {
if (x.contains("BEGIN")) {
flag = true;
return false
} else if (x.contains("END")) {
flag = false
}
flag
}
f
}
Run Code Online (Sandbox Code Playgroud)
这有可能避免定义标志变量吗?他们如何用纯函数式语言解决这个问题?
您可以使用drop/ tail,dropWhile,takeWhile功能:
val filteredList = list1.map(_.trim).dropWhile("BEGIN" !=).tail.takeWhile("END" !=)
Run Code Online (Sandbox Code Playgroud)
tail如果列表为空,注释中提到的将抛出异常,因此如果您希望保持安全,请使用drop(1)而不是tail:
val filteredList = list1.map(_.trim).dropWhile("BEGIN" !=).drop(1).takeWhile("END" !=)
Run Code Online (Sandbox Code Playgroud)
这是我的算法版本,它处理几个BEGIN和END部分(一些疯狂的东西来自我 - 一个小状态机:)
var filteredList1 = list1.map(_.trim).foldLeft(List(None): List[Option[List[String]]]) {
case (None :: rest, "BEGIN") => Some(Nil) :: rest
case (Some(list) :: rest, "END") => None :: Some(list) :: rest
case (Some(current) :: rest, num) => Some(num :: current) :: rest
case (result, _) => result
}.flatten.reverse map (_.reverse)
Run Code Online (Sandbox Code Playgroud)
它返回 List[List[String]]