1

我相信一定有更好的方法来问这个问题,但我想不出。

考虑这个案例类:

case class UserLocation(id: Int, dateTime: DateTime, lat: Double, lon: Double)

我有List[UserLocation]所有用户的所有位置的历史记录,我想过滤这个列表以仅包含每个用户的最新位置。

这是我的做法:

implicit def dateTimeOrdering: Ordering[DateTime] = Ordering.fromLessThan(_ isAfter _)

val locations: List[UserLocation] = bigListOfUserLocations()
val groupedById  = locations.groupBy(_.id)
val sortedByDate = groupedById.map(_._2.sortBy(_.dateTime))
val finalList    = sortedByDate.map(_.head)

这可行,但我想知道是否有更好的方法来做到这一点,提高性能和/或可读性

重要提示:这主要是一个学术问题,我想知道在处理列表时实现这一点的最实用或最惯用的方法,所以像“在收到列表之前在数据库上尝试 xyz”这样的建议不会有帮助

4

2 回答 2

2

你基本上在那里,但你可以将最后两个操作减少为一个:

val finalList = groupedById.map(_._2.maxBy(_.dateTime))

这更具可读性和性能,因为您只需找到组中最大的项目,而无需将其余部分整理好。

于 2016-07-15T12:48:32.537 回答
0

正如@Iadams已经提到的,这里不需要排序。我的解决方案不会提高可读性,但会稍微提高性能(尽管它仍然是O(n)),因为它不会存储用户的所有位置,而是存储最新的位置,一次通过列表:

locations
    .foldLeft(mutable.Map.empty[Int, UserLocation]) {
      case (acc, loc)
        if !acc.contains(loc.id) ||
          acc(loc.id).dateTime < loc.dateTime => acc.updated(loc.id, loc)
      case (acc, _) => acc
    }.map(_._2)
于 2016-08-24T01:06:54.643 回答