繁体   English   中英

分隔符之间的Seq / Array中的Scala过滤器元素

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM