0

我正在编写一个模拟,其中许多操作员从一个队列中工作。在每个时间步,我需要依次检查序列的元素,如果条件通过,则用队列中的项目替换当前值。必须保留队列中剩余的内容以供以后的迭代使用。

我已经编写了一个调用patch来执行此操作的例程,但它看起来不是很整洁。有没有更惯用的方法来实现同样的目标?我希望它相当快,但在风格上仍然很实用。

import scala.annotation.tailrec
import scala.collection.immutable.Queue

object SeqPimp extends App{

    val mySeq = Seq('a', 'B', 'C', 'd', 'E')
    val shortQ = Queue('+','-')
    val longQ = Queue('+','-','*','/','%')

    println(patch(mySeq)(_.isUpper, shortQ))
    //Output:   (List(a, +, -, d, E),Queue())

    println(patch(mySeq)(_.isUpper, longQ))
    //Output:   (List(a, +, -, d, *),Queue(/, %))

    def patch[T](to: Seq[T])(condition: T => Boolean, from: Queue[T]): (Seq[T], Queue[T]) = {
        @tailrec
        def go(acc: Seq[T], remaining: Seq[T], q: Queue[T]): (Seq[T], Queue[T]) = {
            if(acc.size == to.size) (acc.reverse, q)
            else if(q.size == 0) (acc.reverse ++: remaining, q)
            else{
                if(condition(remaining.head)){
                    val (item, q1) = q.dequeue
                    go(item +: acc, remaining.tail, q1)
                }else{
                    go(remaining.head +: acc, remaining.tail, q)
                }
            } 
        }

        go(Nil, to, from)
    }
}
4

1 回答 1

1

像这样的东西...

def patch[T](to: Seq[T])(condition: T => Boolean, from: Queue[T]): (Seq[T], Queue[T]) = {
if (from.isEmpty) (to, from)
else {
  val i = to.indexWhere(condition)
  if (i == -1) (to, from)
  else patch(to.patch(i, Seq(from.head), 1))(condition, from.tail)
}
}

或者您可以通过这种方式简单地丰富 Seq..

object SeqPimp extends App {

  implicit class EnSeq[T](val to: Seq[T]) extends AnyVal{
    def enPatch(condition: T => Boolean, from: Queue[T]): (Seq[T], Queue[T]) = {
      if (from.isEmpty) (to, from)
      else {
        val i = to.indexWhere(condition)
        if (i == -1) (to, from)
        else to.patch(i, Seq(from.head), 1).enPatch(condition, from.tail)
      }
    }
  }

  val mySeq = Seq('a', 'B', 'C', 'd', 'E')
  val shortQ = Queue('+', '-')
  val longQ = Queue('+', '-', '*', '/', '%')

  mySeq.enPatch(_.isUpper, shortQ)
  //Output:   (List(a, +, -, d, E),Queue())

  mySeq.enPatch(_.isUpper, longQ)
  //Output:   (List(a, +, -, d, *),Queue(/, %))

}

编辑

这是def patch性能更好的..但不像以前那么漂亮..

  def patch[T](to: Seq[T])(condition: T => Boolean, from: Queue[T]): (Seq[T], Queue[T]) = {
    @tailrec
    def go(acc: Seq[T], remaining: Seq[T], q: Queue[T]): (Seq[T], Queue[T]) = {
      if (q.isEmpty || remaining.isEmpty) (acc ++ remaining, q)
      else {
        val (accu, rem) = remaining.span(e => !condition(e))
        if (rem.isEmpty) (acc ++ accu, q)
        else go(acc ++ accu.:+(q.head), rem.tail, q.tail)
      }
    }
    go(Nil, to, from)
  }
于 2013-05-19T08:51:37.347 回答