2012-12-09 64 views
2

我有一個不可變列表,我需要交換位置。有沒有簡單的方法來做到這一點?斯卡拉交換位置列表

下面是我的代碼:

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; 
    } 

起初,我嘗試了通過將其轉換爲Array,改變位置,然後再次轉換到列表中。任何簡單的方法?

+3

這裏的關鍵位,正如你提到的,是該名單是不可改變的,所以你不能交換項目。 – Sean

回答

12

一個簡單(但不是非常有效的方式)將

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) 
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個部分:列表中的前綴ii,部分前i & j獨家,j,並j後到來列表的後綴之間。從那裏,它與i & j交換簡單的級聯。它可以更有效的,如果你使用列表緩衝區,甚至更有效的,如果你對可變Array的工作......這樣的

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) 
} 
0

一件事(根據不同的應用,例如你更新點往往等)是使用「拉鍊」,見下文。您可能需要添加「moveTo」方法或類似方法。如果處理不可變列表,可能會有更少的更新。我認爲上面的簡單解決方案可能適用於小型清單。

編輯:可能如果你知道你正在追逐彼此附近等元素可以進行調整

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)