Remove Duplicates from the List recursively

[亡魂溺海] 提交于 2019-12-11 14:38:45

问题


I want to remove duplicates from the list recursively using pattern matching with Scala

here is my input

val xs = List(1,2,3,4,6,3,2,7,9,4)

Tried code:

  def removeDuplicates(xs : List[Int]) : List[Int] = xs match {
  case Nil =>Nil
  case x::ys => { 
      if(ys.contains(x)){
      removeDuplicates(ys)
    } else {
        }
/// ???
  }
}

I was stuck at the question mark, how to appened my result to the mutable list and return it.

Thank you.


回答1:


You're close:

 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)

While this is a brief solution, it isn't tail recursive and therefore vulnerable for stackoverflows - whereas Jean Logearts solution solves the problem.

Here is an alternative solution with an inner function, tailrecursive too:

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)

with a bias to the first elements, but with the result reversed, which can be easily corrected by returning collected.reverse in the Nil case, if it is important.

The outer function serves the job to provide a simple, one-argument interface to the user, so he doesn't need to provide an empty List.

Note, that the solution is crying for a type annotation, since it doesn't depend at all on the List elements being of type Int:

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:


You need to keep track of the current state: already seen elements using a set (for fast lookup), and the new list being constructed:

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



回答3:


Here's a classic approach using an inner function and tail recursion. The tail recursion may not be necessary for small lists but it is easier for me to reason about.

  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)

Of course, distinct is the preferred way to do this but this is a good exercise. distinct can be used to verify your solution though.

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


来源:https://stackoverflow.com/questions/49929630/remove-duplicates-from-the-list-recursively

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!