在scala中交换位置列表

时间:2012-12-09 09:37:04

标签: scala

我有一个不可变的列表,我需要在其中交换位置。有没有简单的方法呢?

以下是我的代码:

def swap(i:Int, j:Int,li:List[T]):List[T]={
        if(i>=li.size && j >=li.size)
            throw new Error("invalie argument");

        val f = li(i)
        li(i) = li(j) //wont work
        li(j) = f;//wont work
        li;
    }

最初,我尝试将其转换为数组,更改位置,然后再将其转换为List。有什么简单的方法吗?

4 个答案:

答案 0 :(得分:13)

这样做很容易(但不是很有效)

val l = List(1,2,3)
l: List[Int] = List(1, 2, 3)

l.updated(0,l(2)).updated(2,l(0))
res1: List[Int] = List(3, 2, 1)

答案 1 :(得分:5)

您只能在O(n)中创建新列表。您可能想要使用不同的数据结构。你可以这样做:

def swap[T](i:Int, j:Int,li:List[T]):List[T]={
    if(i>=li.size || j >=li.size || i >= j)
         throw new Error("invalid argument")

    li.dropRight(li.length - i) ::: (li(j) :: li.dropRight(li.length - j).drop(i+1)) ::: ((li(i) :: li.drop(j + 1)))
}

它不是很优雅,但它会完成这项工作。基本上,我正在对索引i&上的列表进行切片。 j,所以我有5个部分:i之前的列表前缀,ii之间的部分。 j独占,j以及j之后列表的后缀。从那里,它与i&的简单连接j转过身来。如果你使用列表缓冲区可以更有效,如果你将使用可变Array s更高效...

答案 2 :(得分:0)

我不确定这是否是这样做的好方法但是我怎么样这样呢?

def swapElements(list: List[Any], first: Int, second: Int) = {
 def elementForIndex(index: Int, element: Any) = {
   if(index == first) {
     list(second)
   } else if(index == second){
     list(first)
   } else {
     element
   }
 }

 for(element <- ((0 to list.size - 1) zip list).to[List])
   yield elementForIndex(element._1, element._2)
}

答案 3 :(得分:0)

您可能想要尝试的一件事(取决于应用程序,例如您经常更新点等等)是使用&#39; Zipper&#39;,见下文。你可能想要添加一个&#39; moveTo&#39;方法或类似方法。如果处理不可变列表,您可能会有更少的更新。我认为上面的简单解决方案可能最适合小型列表。

编辑:如果你知道你正在追逐彼此附近的元素等,可能会被调整。

case class Zipper[A](focus: A, left: List[A], right: List[A]) {

  def fromZipper: List[A] = left ::: List(focus) ::: right

  /** Will throw NoSuchElementException if try to move beyond start. */

  /** directions are forward and backward across the list. */
  def moveForward: Zipper[A] = Zipper(right.head,left :+ focus,right.tail)
  def moveBackward: Zipper[A] = Zipper(left.last,left.init,focus :: right)

  /** Update the focus element. */
  def update(a: A): Zipper[A] = Zipper(a,left,right)
}


def apply[A](left: List[A], focus: A, right: List[A]): Zipper[A]
  = Zipper(focus,left,right)

def apply[A](xs: List[A]): Zipper[A]
    = Zipper(xs.head,List.empty[A],xs.tail)