Levijatanu Levijatanu - 1 month ago 5
Scala Question

Remove duplicates from list of DateTime objects only by Date component

What is preferred way to remove duplicates from list Joda DateTime objects but only by date component (no time component )

var dates = List[DateTime]()

dates = dates ::: List(new DateTime(2015, 1, 1, 0, 0, 0, 0))
dates = dates ::: List(new DateTime(2011, 1, 1, 0, 0, 0, 1))
dates = dates ::: List(new DateTime(2011, 1, 1, 0, 0, 0, 0)) // different millisOfSecond

println(dates.distinct)


Results in

List(2015-01-01T00:00:00.000+01:00,
2011-01-01T00:00:00.001+01:00,
2011-01-01T00:00:00.000+01:00)

Answer

Write a wrapper case class and override the equals method to do equality based on date component.

case class DateTimeWrapper(dt: DateTime) {
  override def equals(obj: scala.Any): Boolean = obj match {
    case x: DateTime => x.getDayOfMonth == this.dt.getDayOfMonth
    case _ => false
  }
}

Here is the distinct method which uses Set to pick non duplicate elements

def distincts(list: List[DateTime]): List[DateTime] = {
  def helper(set: Set[DateTimeWrapper], list: List[DateTimeWrapper]) = list match {
    case Nil => set
    case x :: xs => if (set contains x) set else set + x
  }
  helper(Set.empty[DateTimeWrapper], list.map(DateTimeWrapper)).toList.map(_.dt)
}

Write an Implicit to make the API look better

implicit class ListUtils(list: List[DateTime]) {
  def distinctElems = distincts(list)
}

Usage:

val dates = List(
  new DateTime(2015, 1, 1, 0, 0, 0, 0),
  new DateTime(2011, 1, 1, 0, 0, 0, 1),
  new DateTime(2011, 1, 1, 0, 0, 0, 0)
)

println(dates.distinctElems.length)