【问题标题】:Get the most recent location of many users获取许多用户的最新位置
【发布时间】:2016-07-15 12:40:12
【问题描述】:

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

考虑这个案例类:

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 之类的建议在您收到清单之前” 不会有帮助

【问题讨论】:

    标签: scala scala-collections list-manipulation


    【解决方案1】:

    您基本上已经完成了,但您可以将最后两个操作简化为一个:

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

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

    【讨论】:

    • 哦,很有趣。我不知道maxBymethod。谢谢
    • 小心,因为maxBy 是一个偏函数 - scala> List[(Int, Int)]().maxBy(_._1) java.lang.UnsupportedOperationException: empty.maxBy
    【解决方案2】:

    正如@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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多