我想使用与Scala匹配的模式
以递归方式从列表中删除重复项这是我的输入
val xs = List(1,2,3,4,6,3,2,7,9,4)
尝试过的代码:
def removeDuplicates(xs : List[Int]) : List[Int] = xs match {
case Nil =>Nil
case x::ys => {
if(ys.contains(x)){
removeDuplicates(ys)
} else {
}
/// ???
}
}
我被困在问号上,如何将我的结果添加到可变列表并返回它。
谢谢。
答案 0 :(得分:3)
您需要跟踪当前状态:已经看到的元素使用集合(用于快速查找),以及正在构建的新列表:
@tailrec
def removeDuplicatesRec(
remaining: List[Int],
seen: Set[Int],
acc: List[Int]
): List[Int] = remaining match {
case Nil => acc
case head :: tail =>
if (!seen.contains(head)) removeDuplicatesRec(tail, seen + head, acc :+ head)
else removeDuplicatesRec(tail, seen, acc)
}
def removeDuplicates(xs: List[Int]): List[Int] =
removeDuplicatesRec(xs, Set.empty, List.empty)
答案 1 :(得分:3)
你很亲密:
def removeDuplicates(xs : List[Int]) : List[Int] = xs match {
case Nil => Nil
case x::ys => if (ys.contains (x)) removeDuplicates (ys) else
x :: removeDuplicates (ys)
}
scala> removeDuplicates (List (1,2,3,4,6,3,2,7,9,4))
res143: List[Int] = List(1, 6, 3, 2, 7, 9, 4)
虽然这是一个简短的解决方案,但它不是尾递归的,因此容易受到堆栈溢出的影响 - 而Jean Logearts解决方案可以解决这个问题。
这是一个带内部函数的替代解决方案,也是tailrecursive:
def removeDuplicates (xsOuter : List[Int]) : List[Int] = {
@annotation.tailrec
def removeDuplicates (xs: List[Int], collected: List[Int]) : List[Int] = xs match {
case Nil => collected
case x :: ys => if (collected.contains (x)) removeDuplicates (ys, collected) else
removeDuplicates (ys, x :: collected)
}
removeDuplicates (xsOuter, Nil)
}
scala> removeDuplicates (List (1,2,3,4,6,3,2,7,9,4))
res151: List[Int] = List(9, 7, 6, 4, 3, 2, 1)
偏向第一个元素,但结果反转,如果重要的话,可以通过在Nil情况下返回collected.reverse
来轻松纠正。
外部函数为作业提供了一个简单的单参数接口,因此他不需要提供一个空列表。
请注意,该解决方案正在为类型注释而哭泣,因为它根本不依赖于Int类型的List元素:
scala> def removeDuplicates [A] (xsOuter : List[A]) : List[A] = {
|
| @annotation.tailrec
| def removeDuplicates (xs: List[A], collected: List[A]) : List[A] = xs match {
| case Nil => collected
| case x :: ys => if (collected.contains (x)) removeDuplicates (ys, collected) else
| removeDuplicates (ys, x :: collected)
| }
|
| removeDuplicates (xsOuter, Nil)
| }
removeDuplicates: [A](xsOuter: List[A])List[A]
scala> removeDuplicates (List (1,2,3,4,6,3,2,7,9,4))
res152: List[Int] = List(9, 7, 6, 4, 3, 2, 1)
答案 2 :(得分:1)
这是使用内部函数和尾递归的经典方法。对于小型列表,尾部递归可能不是必需的,但我更容易理解。
def removeDuplicates(xs : List[Int]) : List[Int] = {
@scala.annotation.tailrec
def accumulator(xs: List[Int], acc: List[Int]):List[Int] = xs match {
case Nil => acc
case h::t if(!acc.contains(h)) => accumulator(t, h :: acc)
case h::t if(acc.contains(h)) => accumulator(t, acc)
}
accumulator(xs, List[Int]())
}
scala> removeDuplicates(List(1,2,3,4,6,3,2,7,9,4))
res16: List[Int] = List(9, 7, 6, 4, 3, 2, 1)
当然,distinct
是首选方法,但这是一个很好的练习。 distinct
可用于验证您的解决方案。
scala> List(1,2,3,4,6,3,2,7,9,4).distinct == removeDuplicates(List(1,2,3,4,6,3,2,7,9,4)).sorted
res21: Boolean = true