2017-04-10 55 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集合一致。