2012-12-09 4 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; 
    } 

는 처음에, 내가, 배열로 변환 위치를 변경 한 후 다시 목록으로 변환하여 시도 :

다음은 내 코드입니다. 쉬운 방법?

+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 개 부품이 : 목록의 접두사를 i, i, 부분 전에 i & 독점 j, jj 다음에 오는 목록의 접미사 사이. 거기에서, 그것은 단순한 연결 i swaped입니다. 당신은 변경할 수 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) 
관련 문제