Anthony
Anthony

Reputation: 35958

How to run distinct on string of case class in a list?

scala> case class Color (name: String, shade: String)
defined class Color

scala> val colors = List[Color](Color("red", "light"), Color("green", "dark"), Color("red", "dark"))
colors: List[Color] = List(Color(red,light), Color(green,dark), Color(red,dark))

I need to find out if there are any duplicate shades (i.e. "dark" is a duplicate in the list above)

How can I do this? I can't just run colors.distinct because that will check for distinct on all properties (name and shade) but I'm only interested in finding duplicates of shade

Upvotes: 1

Views: 696

Answers (3)

slavik
slavik

Reputation: 1303

Let's introduce new function

def distinctBy[A, B](xs: List[A])(key: A => B): List[A] = {
  val seen = mutable.HashSet[B]()
  xs.filter { x =>
    val k = key(x)
    if (!seen(k)) {
      seen += k
      true
    } else false
  }
}

and

distinctBy(colors)(_.shade)

results in

res0: List[Color] = List(Color(red,light), Color(green,dark))

Upvotes: 0

Alejandro Alcalde
Alejandro Alcalde

Reputation: 6220

If you only want to know if there is any duplicates, I think this could be a solution:

colors.map(_.shade).distinct

If the length of that is less than the length of colors, you have duplicates in the list. That is, if:

colors.map(_.shade).distinct.size == colors.size

Then there aren't duplicates.

Upvotes: 3

mukesh210
mukesh210

Reputation: 2892

One possible solution would be to groupBy and then take head:

  case class Color (name: String, shade: String)
  val colors = List[Color](Color("red", "light"), Color("green", "dark"), Color("red", "dark"))
  println(colors.groupBy(_.shade).map(x => x._2.head).toList)

Another way is by using Scala reflect:

  import scala.reflect.internal.util.Collections
  println(Collections.distinctBy(colors)(_.shade))

Upvotes: 3

Related Questions