2014-04-16 39 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