滚动Scala List或Seq的内置方法

时间:2015-06-27 17:32:32

标签: list scala

我正在尝试滚动列表,例如:

class UpdateServer extends Job implements SelfHandling, ShouldQueue
{
    use InteractsWithQueue, SerializesModels;
    protected $id;

    public function __construct($id)
    {
       $this->id = $id;
    }

    public function handle(){
       $server = Server::findOrFail($this->id);

       //preparing the packet
       $test = new RAGBuffer();
       $test->addChar('255');
       $test->addChar('1');
       $test->addShort(1 | 8);

       //finding the server
       $serverGame = new RAGServer($server->server_ip);

       //Get server info
       $status = $serverGame->sendPacket($test);

       $server->onlinePlayers = $status->getOnline();
       $server->peakPlayers = $status->getPeak();
       $server->maxPlayers = $status->getMax();

       if (!$server->save()) {
           //error ocurred
       }
   }
}

我查看了scala-lang.org,似乎无法找到符合我要求的任何内容。

是否有内置滚动列表的方法?

如果没有,有没有比这更有效的方法:

val notRolled = (1 to 5).toList       // List(1,2,3,4,5)

val rolledBy1 = rollList(notRolled,1) // List(2,3,4,5,1)
val rolledBy2 = rollList(notRolled,2) // List(3,4,5,1,2)
val rolledBy3 = rollList(notRolled,3) // List(4,5,1,2,3)
val rolledBy4 = rollList(notRolled,4) // List(5,1,2,3,4)
val rolledBy5 = rollList(notRolled,5) // List(1,2,3,4,5)

val rolledByM1 = rollList(notRolled,-1) // List(5,1,2,3,4)
val rolledByM2 = rollList(notRolled,-2) // List(4,5,1,2,3)
val rolledByM3 = rollList(notRolled,-3) // List(3,4,5,1,2)
val rolledByM4 = rollList(notRolled,-4) // List(2,3,4,5,1)
val rolledByM5 = rollList(notRolled,-5) // List(1,2,3,4,5)

6 个答案:

答案 0 :(得分:5)

使用enrich-my-library模式,您可以将roll方法直接添加到所有集合中,以便您可以调用myList.roll(2),而不是roll(myList, 1)

使用通用CanBuildFrom模式,您可以roll在这些集合上返回最佳类型(以便roll上的List将返回{{1} } {} List上的roll将返回Iterable)。

总之,这是一个遵循这些模式的选项:

Iterable

这允许您执行以下某些操作:

import scala.collection.generic.CanBuildFrom
import scala.collection.TraversableLike

implicit class TraversableWithRoll[A, Repr <: Traversable[A]](val xs: TraversableLike[A, Repr]) extends AnyVal {
  def roll[That](by: Int)(implicit bf: CanBuildFrom[Repr, A, That]): That = {
    val builder = bf()
    val size = xs.size
    builder.sizeHint(xs)
    val leftBy = if (size == 0) 0 else ((by % size) + size) % size
    builder ++= xs.drop(leftBy)
    builder ++= xs.take(leftBy)
    builder.result
  }
}

注意rich-my-library模式启用的流畅语法的好处,以及使用隐式List(1, 2, 3, 4, 5).roll(2) //List(4,5,1,2,3) Seq(3, 4, 5).roll(-1) //Seq(5, 3, 4) 启用的更强类型。

答案 1 :(得分:0)

这是以功能方式模拟循环列表的一种方法。我这样做是为了让积极的i做一个正确的转变而一个负的左转。这与问题的反面相反,但我觉得这更自然。

def shift[T](c: List[T], i: Int) = { 
   if(c.isEmpty) c
   else {
      val (h,t) = if (i >= 0) c.splitAt(c.size - i%c.size)
            else c.splitAt(- i%c.size) 
      t ++ h
   }
}

以下是REPL中的一些示例:

cala> shift(List(1,2,4), 1)
res: List[Int] = List(4, 1, 2)

scala> shift(List(1,2,4), 2)
res: List[Int] = List(2, 4, 1)

scala> shift(List(1,2,4), 3)
res: List[Int] = List(1, 2, 4)

scala> shift(List(1,2,4), 4)
res: List[Int] = List(4, 1, 2)

scala> shift(List(1,2,4), 5)
res: List[Int] = List(2, 4, 1)

scala> shift(List(1,2,4), 6)
res: List[Int] = List(1, 2, 4)

scala> shift(List(1,2,4), -1)
res60: List[Int] = List(2, 4, 1)

scala> shift(List(1,2,4), -2)
res: List[Int] = List(4, 1, 2)

scala> shift(List(1,2,4), -3)
res: List[Int] = List(1, 2, 4)

scala> shift(List(1,2,4), -4)
res: List[Int] = List(2, 4, 1)

scala> shift(List(1,2,4), -5)
res: List[Int] = List(4, 1, 2)

scala> shift(List(1,2,4), -6)
res: List[Int] = List(1, 2, 4)

答案 2 :(得分:0)

def rotate[A] (list: List[A], by: Int) = {
    if (list.isEmpty) list
    else {
        val shift = (by % list.size + list.size) % list.size
        val (l, r) = list.splitAt(shift)
        r ++ l
    }
}

val list = List(1, 2, 3, 4, 5)
rotate(list, 1) // List(2, 3, 4, 5, 1)
rotate(list, 2) // List(3, 4, 5, 1, 2)
rotate(list, -1) // List(5, 1, 2, 3, 4)
rotate(list, -2) // List(4, 5, 1, 2, 3)

rotate(list, -9) // List(2, 3, 4, 5, 1)

答案 3 :(得分:0)

这是我纯粹的功能性非常简单的命题:

def circ[A]( L: List[A], times: Int ): List[A] = {

    if ( times == 0 || L.size < 2 ) L
    else circ(L.drop(1) :+ L.head , times-1)
}

val G = List("1a","2b","3c")

println( circ(G,1) ) //List(2b, 3c, 1a)
println( circ(G,2) ) //List(3c, 1a, 2b)
println( circ(G,3) ) //List(1a, 2b, 3c)
println( circ(G,4) ) //List(2b, 3c, 1a)

添加次数&lt; 0(向后滚动):

def circ[A]( L: List[A], times: Int ): List[A] = {
    if ( times == 0 || L.size < 2 ) L
    else if ( times < 0 ) circ(L.reverse,-times).reverse 
    else                  circ(L.drop(1) :+ L.head , times-1)
}

答案 4 :(得分:0)

鉴于:

val notRolled = (1 to 5).toList 

假设我们想要使用shift = 3

进行旋转
val shift = 3

notRolled.zipWithIndex.groupBy(_._2 < shift).values.flatten.map(_._1)

对于负值,我们应该添加5(列表大小),因此对于shift = -3,我们将计算

val shift = -3
notRolled.zipWithIndex.groupBy(_._2 < 2).values.flatten.map(_._1)

答案 5 :(得分:0)

我会在上面了解CanBuildFrom的内容,只要我更好地了解Scala(!),但与此同时,为了编写Burrows-Wheeler,我必须做到这一点。变换算法。在这里,没有take()drop(),空集合上没有错误(是的,副作用代码):

def roll[A](xs: Traversable[A]): Iterator[Traversable[A]] = {
  var front = xs
  var back = collection.mutable.Buffer[A]()

  Iterator.continually(front ++ back).takeWhile { _ =>
    val done = front.isEmpty
    if (!done) {
      back :+= front.head
     front = front.tail
   }
   !done
  }
}