Skip to content

Commit

Permalink
Added Chain#distinct and NonEmptyChain#distinct to match `List#di…
Browse files Browse the repository at this point in the history
…stinct` and `NonEmptyList#distinct` (#2579)

* Chain#distinct

* NonEmptyChain#distinct

* fmt
  • Loading branch information
fmsbeekmans authored and kailuowang committed Nov 6, 2018
1 parent fe9a6e7 commit 9807343
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 0 deletions.
19 changes: 19 additions & 0 deletions core/src/main/scala/cats/data/Chain.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Chain._

import scala.annotation.tailrec
import scala.collection.immutable.SortedMap
import scala.collection.immutable.TreeSet
import scala.collection.mutable.ListBuffer

/**
Expand Down Expand Up @@ -358,6 +359,24 @@ sealed abstract class Chain[+A] {
iterX.hasNext == iterY.hasNext
}

/**
* Remove duplicates. Duplicates are checked using `Order[_]` instance.
*/
def distinct[AA >: A](implicit O: Order[AA]): Chain[AA] = {
implicit val ord = O.toOrdering

var alreadyIn = TreeSet.empty[AA]

foldLeft(Chain.empty[AA]) { (elementsSoFar, b) =>
if (alreadyIn.contains(b)) {
elementsSoFar
} else {
alreadyIn += b
elementsSoFar :+ b
}
}
}

def show[AA >: A](implicit AA: Show[AA]): String = {
val builder = new StringBuilder("Chain(")
var first = true
Expand Down
18 changes: 18 additions & 0 deletions core/src/main/scala/cats/data/NonEmptyChain.scala
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,24 @@ class NonEmptyChainOps[A](val value: NonEmptyChain[A]) extends AnyVal {
/** Reverses this `NonEmptyChain` */
final def reverse: NonEmptyChain[A] =
create(toChain.reverse)

/**
* Remove duplicates. Duplicates are checked using `Order[_]` instance.
*/
final def distinct[AA >: A](implicit O: Order[AA]): NonEmptyChain[AA] = {
implicit val ord = O.toOrdering

var alreadyIn = TreeSet(head: AA)

foldLeft(NonEmptyChain(head: AA)) { (elementsSoFar, b) =>
if (alreadyIn.contains(b)) {
elementsSoFar
} else {
alreadyIn += b
elementsSoFar :+ b
}
}
}
}

sealed abstract private[data] class NonEmptyChainInstances extends NonEmptyChainInstances1 {
Expand Down
6 changes: 6 additions & 0 deletions tests/src/test/scala/cats/tests/ChainSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -174,4 +174,10 @@ class ChainSuite extends CatsSuite {
}
}
}

test("Chain#distinct is consistent with List#distinct") {
forAll { a: Chain[Int] =>
a.distinct.toList should ===(a.toList.distinct)
}
}
}
6 changes: 6 additions & 0 deletions tests/src/test/scala/cats/tests/NonEmptyChainSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,10 @@ class NonEmptyChainSuite extends CatsSuite {
ci.reverse.toChain should ===(ci.toChain.reverse)
}
}

test("NonEmptyChain#distinct is consistent with List#distinct") {
forAll { ci: NonEmptyChain[Int] =>
ci.distinct.toList should ===(ci.toList.distinct)
}
}
}

0 comments on commit 9807343

Please sign in to comment.