我正在编写一个模拟,其中许多操作员从单个队列中获取工作。在每个时间步骤我需要按顺序检查序列的元素,如果条件通过,则用队列中的项替换当前值。必须保留队列中剩余的内容以供以后迭代。
我已经编写了一个名为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)
}
}
答案 0 :(得分: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)
}