2017-04-10 58 views
1

我有這樣的Scala代碼,但它並沒有給排序列表:如果我只用這條線之下我得到的排序列表沒有排序斯卡拉光滑查詢

val itemList = items.sortBy(_.name).filter(_.categoryId === catId).drop(start) 

def getItemsByCategoryId(catId: Long, start: Int = 0, limit: Option[Int] = None): Future[Seq[(Item, Seq[String])]] = { 

    val itemList = items.sortBy(_.name).filter(_.categoryId === catId).drop(start) 

    val q = for { 
    (j, pair) <- itemList joinLeft (groups join tags on (_.tagId === _.id)) on (_.id === _._1.itemId) 
    } yield (j, pair) 

    db.run(q.result).map { (row) => 
    row.groupBy(_._1).map { x => 
     val tags = x._2.map(_._2).flatten 
     (x._1, tags.map(_._2.keyword)) 
    }.toSeq 
    } 
} 

join/groupBy操作以某種方式影響排序?

+1

是的,他們做了,並在一個非常大的方式。所以如果你想要排序的結果,那麼你將不得不再次排序。 –

回答

1

TraversableLike.groupBy返回immutable.Map。插入順序僅針對Map值保留,因爲實現在for -loop中迭代其元素。對面的鑰匙確實沒有訂單。它們是所提供功能的結果。

斯卡拉標準收集庫沒有這個問題的開箱即用的解決方案。因爲我有完全相同的問題,我寫我自己orderedGroupBy的一個擴展Seq返回一個immutable.ListMap代替:

implicit class SeqWithOrderedGroupBy[A](xs: Seq[A]) { 

    /** 
    * Partitions this traversable collection into a map of traversable collections according to some discriminator function. 
    * Preserves insertion order. 
    * 
    * @param f the discriminatior function. 
    * @tparam K the type of keys returned by the discriminator function. 
    * @return An ordered map from keys to seq. 
    */ 
    def orderedGroupBy[K](f: A => K): immutable.ListMap[K, Seq[A]] = { 
    val m = mutable.ListBuffer.empty[(K, mutable.Builder[A, Seq[A]])] 
    for (elem <- xs) { 
     val key = f(elem) 
     val builder = m.find(_._1 == key) 
     .map(_._2) 
     .getOrElse { 
      val bldr = mutable.Seq.newBuilder[A] 
      m.append((key, bldr)) 
      bldr 
     } 

     builder += elem 
    } 
    val b = immutable.ListMap.newBuilder[K, Seq[A]] 
    for ((k, v) <- m) 
     b += ((k, v.result)) 

    b.result 
    } 
} 

聲明:我沒有比較上面的代碼中的表現TraversableLike.groupBy。這對我的目的來說已經足夠了,但可能會更糟。雖然任何改進都是受歡迎的

+0

優秀 - 正是我需要的Scala新手 – srvy

2

GroupBy不保留排序,因爲它返回一個映射。這種行爲與Scala集合一致。