在 Scala `List` 中查找由两个元素分隔的所有切片

Finding all slices delimited by two elements in Scala `List`

在 Scala 中,根据两个元素的位置 selecting 列表元素的正确方法是什么?假设我有下面的列表,我想 select 2 到 7 之间的所有元素,包括它们(注意:不大于 than/smaller,但在 2 之后和 7 之前的元素列表):

scala> val l = List(1, 14, 2, 17, 35, 9, 12, 7, 9, 40)
l: List[Int] = List(1, 14, 2, 17, 35, 9, 12, 7, 9, 40)

scala> def someMethod(l: List[Int], from: Int, to: Int) : List[Int] = {
     | // some code here
     | }
someMethod: (l: List[Int], from: Int, to: Int)List[Int]

scala> someMethod(l, 2, 7)
res0: List[Int] = List(2, 17, 35, 9, 12, 7)

预期输出:

您正在寻找 slice:

@ l.slice(2, 7)
res1: List[Int] = List(2, 17, 35, 9, 12)

@ l.slice(2, 8)
res2: List[Int] = List(2, 17, 35, 9, 12, 7)

太糟糕了,正则表达式引擎只能处理字符串,不能处理一般列表——如果你能找到像 L.*?R 这样带有两个任意定界符 LR。由于它不适用于正则表达式,因此您必须自己构建一个小自动机。这是一种方法:

@annotation.tailrec 
def findDelimitedSlices[A](
  xs: List[A],
  l: A,
  r: A,
  revAcc: List[List[A]] = Nil
): List[List[A]] = {
  xs match {
    case h :: t => if (h == l) {
      val idx = xs.indexOf(r)
      if (idx >= 0) {
        val (s, rest) = xs.splitAt(idx + 1)
        findDelimitedSlices(rest, l, r, s :: revAcc)
      } else {
        revAcc.reverse
      }
    } else {
      findDelimitedSlices(t, l, r, revAcc)
    }
    case Nil => revAcc.reverse
  }
}

输入:

for (example <- List(
  List(1, 2, 2, 2, 3, 4, 7, 8),
  List(1, 2, 3, 4, 7, 7, 7, 8),
  List(1, 2, 3, 4, 7, 1, 2, 3, 5, 7, 8)
)) {
  println(findDelimitedSlices(example, 2, 7))
}

输出:

List(List(2, 2, 2, 3, 4, 7))
List(List(2, 3, 4, 7))
List(List(2, 3, 4, 7), List(2, 3, 5, 7))