[英]Scala filter elements in Seq/Array between separators
我有一个数组,如:
val array = Array("Hello", "```", "blabla", "anything", "filler", "```", "another filler")
filter
方法仅在数组或Seq的每个元素上
array.filter(s => !s.startsWith("```"))
> Array(Hello, blabla, anything, filler, another filler)
我想删除分隔符"```"
之间的所有内容。 最终结果将是
Array("Hello", "another filler")
该问题类似于由Stack解决的Bracket编码任务 。 您如何在纯FP中完成此任务?
进一步
有2个部分,以分隔符"```"
分隔。
注意:分隔符不相等,但以"```"
开始。 有一个"```scala"
val input = Array("Hello", "```", "blabla1", "```", "blabla2", "```scala","blabla3", "filler", "```", "blabla4")
filteredOutput = Array("Hello", "blabla2", "blabla4")
PS:也许您发现了,该解决方案从markdown文件中过滤了代码注释。
这应该满足您的更新要求。
def condense(ss: Seq[String], delimiter: String): Seq[String] = {
val start = ss.indexWhere(_.startsWith(delimiter))
val stop = ss.indexWhere(_.startsWith(delimiter), start + 1)
if (stop < 0) ss
else condense(ss.patch(start, Seq(), stop-start+1), delimiter)
}
condense(input, "```") // res0: Array[String] = Array(Hello, blabla2, blabla4)
我不确定这是否一定是最好的方法,但是我想出的一种方法是将其折叠:
val (filteredOutput: Array[String], _) =
input.foldLeft((Array[String](), true)) {
case ((output: Array[String], include: Boolean), sep) if sep.startsWith("```") => (output, !include)
case ((output: Array[String], true), next: String) => (output :+ next, true)
case ((output: Array[String], false), _) => (output, false)
}
这是一个更新的版本,可以应对有关奇数个分隔符的更新要求:
val filteredOutput = {
val (workingOutput: Array[String], _, discard: List[String]) =
input.foldLeft((Array[String](), true, List[String]())) {
case ((output: Array[String], include: Boolean, _), sep) if sep.startsWith("```") =>
(output, !include, if (include) List(sep) else Nil)
case ((output: Array[String], true, _), next: String) =>
(output :+ next, true, Nil)
case ((output: Array[String], false, discard: List[String]), next: String) =>
(output, false, next :: discard)
}
workingOutput ++ discard.reverse
}
另一个版本,避免使用索引:
val input = Array("Hello", "```", "blabla1", "```",
"blabla2", "```scala", "blabla3", "filler", "```", "blabla4")
def condense(xs: Array[String], acc: Array[String] = Array()): Array[String] = {
if (xs.isEmpty) acc
else {
val (before, after) = xs.span(!_.startsWith("```"))
val remaining = after.drop(1).dropWhile(!_.startsWith("```"))
if (remaining.isEmpty) // unclosed commment
acc ++ xs
else condense(remaining.drop(1), acc ++ before)
}
}
condense(input) //> res0: Array[String] = Array(Hello, blabla2, blabla4)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.