如何从另一个列表中删除列表的每个实例?

时间:2016-07-30 03:48:08

标签: algorithm scala scala-collections

我有一个清单

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) }

然后我无法想出去那里,这让我想知道我是否走在正确的轨道上。

2 个答案:

答案 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变为可变。