在 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)
预期输出:
- 对于不包含 2 and/or 7 的列表:空列表
- 输入:
(1, 2, 2, 2, 3, 4, 7, 8)
;输出:(2, 2, 2, 3, 4, 7)
- 输入:
(1, 2, 3, 4, 7, 7, 7, 8)
;输出:(2, 3, 4, 7)
- 输入:
(1, 2, 3, 4, 7, 1, 2, 3, 5, 7, 8)
;输出:((2, 3, 4, 7), (2, 3, 5, 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
这样带有两个任意定界符 L
和R
。由于它不适用于正则表达式,因此您必须自己构建一个小自动机。这是一种方法:
@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))
在 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)
预期输出:
- 对于不包含 2 and/or 7 的列表:空列表
- 输入:
(1, 2, 2, 2, 3, 4, 7, 8)
;输出:(2, 2, 2, 3, 4, 7)
- 输入:
(1, 2, 3, 4, 7, 7, 7, 8)
;输出:(2, 3, 4, 7)
- 输入:
(1, 2, 3, 4, 7, 1, 2, 3, 5, 7, 8)
;输出:((2, 3, 4, 7), (2, 3, 5, 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
这样带有两个任意定界符 L
和R
。由于它不适用于正则表达式,因此您必须自己构建一个小自动机。这是一种方法:
@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))