2016-07-15 24 views
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) 

這工作,但我想知道的是,是否有更好的方式來做到這一點,從而提高性能和/或可讀性

重要提示:這主要是一個學術問題,我想知道在操作的列表實現這一目標的最performatic或最習慣的方法,所以像建議「嘗試在數據庫中的xyz收到名單之前」不會有幫助

回答

2

你基本上沒有,但你可以減少最後兩個操作一個具有:

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

這是更具可讀性,更高性能,因爲你只要找到該組中的最大項目wihtout需要到其餘的按順序排列。

+0

哦,非常有趣。我沒有意識到這種'maxBy'方法。謝謝 –

+1

要小心,因爲'maxBy'是部分功能 - '斯卡拉>列表[(INT,INT)()maxBy(_._ 1) java.lang.UnsupportedOperationException:empty.maxBy' –

0

正如由@Iadams已經述及,也沒有必要在這裏進行排序。

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) 
: 我的解決方案並不在列表中提高可讀性,但提高性能一點(雖然它仍然 O(n)),因爲它不會存儲用戶的所有位置,但最近的一次,在一個通