2014-04-16 42 views
3

我們在Playframework上有一個小型Scala項目。我試圖做一切反應,並偶然發現一個問題。如何根據合併規則將2個統計員合併爲一個

我有兩個Enumerator [A]實例,表示按日期排序的DB值。 我需要將它們作爲單個Enumerator [A]保留日期排序。我還沒有在Enumerator [A]中找到任何解決方案,所以我在單個集合中累積了A,並在之後進行排序。

case class A(
    created: Date, 
    data: String 
) 

val as: Enumerator[A] = findByAOrderedByCreated() 
val bs: Enumerator[A] = findByBOrderedByCreated() 

什麼是被動的方式來處理這個問題?

回答

2

這裏是一個解決方案,將使用對元件的任何Ordering任何數量Enumerator值的工作:

import play.api.libs.iteratee._ 
import scala.concurrent._ 

object MergeEnums { 
    def apply[E: Ordering](enums: Enumerator[E]*)(implicit executor: ExecutionContext) = new Enumerator[E] { 
    def apply[A](iter: Iteratee[E, A]) = { 
     case class IterateeReturn(o: Option[(Promise[Promise[IterateeReturn]], E)]) 

     val failP = Promise() 
     val failPF = failP.future 
     val initState = Future.traverse(enums) { enum => 
     val p = Promise[IterateeReturn]() 
     enum.run(Iteratee.foldM(p) { (oldP: Promise[IterateeReturn], elem: E) => 
      val p = Promise[Promise[IterateeReturn]]() 
      oldP success IterateeReturn(Some(p, elem)) 
      p.future 
     } map { promise => 
      promise success IterateeReturn(None) 
     }) onFailure { case t => failP failure t } 
     p.future 
     } map (_.map(_.o).flatten.toList) 

     Enumerator.unfoldM(initState) { fstate => 
     Future.firstCompletedOf(Seq(fstate, failPF)) map { state => 
      state.sortBy(_._2) match { 
      case Nil => None 
      case (oldP, elem) :: tail => 
       val p = Promise[IterateeReturn]() 
       oldP success p 
       val newState = p.future.map(_.o.map(_ :: tail).getOrElse(tail)) 
       Some(newState, elem) 
      } 
     } 
     } apply iter 
    } 
    } 
} 

它創建一個Iteratee適用於傳遞在每個EnumeratorEnumerator到給排序的元素。 Iteratee實例和Enumerator通過向對方發送Promise實例(因此是Promise[Promise[IterateeReturn]]等)進行通信。

+0

不錯的解決方案:) –

+0

謝謝:)這意味着許多來自Play技術領導。 – wingedsubmariner

+0

對不起,花了我一大筆時間才終於開始使用它 – mavarazy