Skip to content

Instantly share code, notes, and snippets.

@diversit
Created July 29, 2015 08:26
Show Gist options
  • Save diversit/1ceea1c8cf84a44ecbc8 to your computer and use it in GitHub Desktop.
Save diversit/1ceea1c8cf84a44ecbc8 to your computer and use it in GitHub Desktop.
Distinct elements of a List (or Seq) based on a property of the element
/**
* Extends a List[A] with a 'distinctOn' method to be able to distinct the elements
* of a list based on an element property.
*
* For example:
* In a List of Subscription's, we only want to send a certain Subscription.subscriber
* a message once even though the subscriber has multiple subscriptions.
* {{{
* subscriptions.distinctOn(_.subscriber) // returns List[Subscription] with unique subscribers
* }}}
*
* Another way to do this, is just to map the Subscription to subscribers and distinct on that list.
* This only works if you do not need any other property of the Subscription anymore.
* {{{
* subscriptions.map(_.subscriber).distinct // returns List[Subscriber] !!
* }}}
*/
implicit class DistinctFunctionSeq[A](val list: List[A]) extends AnyVal {
/**
* Returns a list of type A where all items whould be unique if
* function 'f' would be applied on each element on the list.
*
* This can be used to distinct a list based on a property of type A.
* For example, a list with persons where person.city is unique.
*
* Note that the resulting function contains the elements of the list in
* reversed order!!
*
* @param f Function to map element A into a B which is used to determine whether the element is unique.
* @tparam B Type of mapping of A
*/
def distinctOn[B](f: A => B): List[A] = list.foldLeft(List.empty[A]) { (acc, elem) =>
val value = f(elem)
// check if accumelator already contains an element with same value
acc.find(item => f(item) == value) match {
case Some(_) => acc // if found, do not add but return accumelation
case None => elem :: acc // if not found, add elem to accumelation
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment