我有一个清单
val l = List(1,2,3,2,6,4,2,3,4,2,1,3,6,3,2)
我希望删除特定序列的每个实例,例如(2,3)
所以期望的输出是......
List(1,2,6,4,4,2,1,3,6,3,2)
在Scala中实现此目的的最简单/最惯用的方法是什么?
到目前为止,我已经尝试过这样做了。
l.sliding(2).filter{ _!=List(2,3) }
然后我无法想出去那里,这让我想知道我是否走在正确的轨道上。
答案 0 :(得分:1)
def stripFrom[A](lst: List[A], x: List[A]): List[A] =
if (lst.containsSlice(x) && x.length > 0)
stripFrom(lst.patch(lst.indexOfSlice(x), List(), x.length), x)
else lst
概念证明:
scala> stripFrom(List(1,2,3,2,6,4,2,3,4,2,1,3,6,3,2), List(2,3))
res3: List[Int] = List(1, 2, 6, 4, 4, 2, 1, 3, 6, 3, 2)
scala> stripFrom(List(1,2,3,2,6,4,2,3,4,2,1,3,6,3,2), List(4,2))
res4: List[Int] = List(1, 2, 3, 2, 6, 3, 1, 3, 6, 3, 2)
scala> stripFrom(List(1,2,3,2,6,4,2,3,4,2,1,3,6,3,2), List(4,2,3,4))
res5: List[Int] = List(1, 2, 3, 2, 6, 2, 1, 3, 6, 3, 2)
scala> stripFrom(List(1,2,3,2,6,4,2,3,4,2,1,3,6,3,2), List(2))
res6: List[Int] = List(1, 3, 6, 4, 3, 4, 1, 3, 6, 3)
答案 1 :(得分:1)
您可以递归地遍历列表,一次消耗列表头部的元素,并将所需的元素累积到结果列表中,同时丢弃匹配的不合需要的序列。一个简单的尾递归示例可以这样工作:
@annotation.tailrec
def filterList[A](list: List[A], acc: List[A] = Nil): List[A] = list match {
case 2 :: 3 :: tail => filterList(tail, acc)
case head :: tail => filterList(tail, head :: acc)
case Nil => acc.reverse
}
scala> val l = List(1,2,3,2,6,4,2,3,4,2,1,3,6,3,2)
scala> filterList(l)
res0: List[Int] = List(1, 2, 6, 4, 4, 2, 1, 3, 6, 3, 2)
或者更一般地,您可以使用startsWith
检查List
的当前迭代是否以您要删除的序列开头。
@annotation.tailrec
def filterList[A](list: List[A], subList: List[A], acc: List[A] = Nil): List[A] = list match {
case l if(list startsWith subList) => filterList(l.drop(subList.length), subList, acc)
case head :: tail => filterList(tail, subList, head :: acc)
case Nil => acc.reverse
}
scala> filterList(l, List(2, 3))
res4: List[Int] = List(1, 2, 6, 4, 4, 2, 1, 3, 6, 3, 2)
如果性能问题,您可以使acc
变为可变。