[scala] Scala 목록을 만드는 데 선호되는 방법

Scala에서 불변 목록을 구성하는 방법은 여러 가지가 있습니다 (아래 인위적인 예제 코드 참조). 변경 가능한 ListBuffer를 사용하고, var목록을 만들고 수정하고, 꼬리 재귀 방법을 사용하고 , 아마도 내가 모르는 다른 방법을 사용할 수 있습니다 .

본능적으로 ListBuffer를 사용하지만 그렇게 할 이유가 없습니다. 목록을 만드는 데 선호되는 방법이나 관용적 인 방법이 있습니까? 아니면 한 방법에 가장 적합한 상황이 있습니까?

import scala.collection.mutable.ListBuffer

// THESE are all the same as: 0 to 3 toList.
def listTestA() ={
    var list:List[Int] = Nil

    for(i <- 0 to 3)
        list = list ::: List(i)
    list
}


def listTestB() ={
    val list = new ListBuffer[Int]()

    for (i <- 0 to 3)
        list += i
    list.toList
}


def listTestC() ={
    def _add(l:List[Int], i:Int):List[Int] = i match {
        case 3 => l ::: List(3)
        case _ => _add(l ::: List(i), i +1)
    }
    _add(Nil, 0)
}



답변

ListBuffer일정 시간 추가 및 일정 시간 변환을 List.

List 불변이며 일정한 시간 앞에 추가되고 선형 시간 추가가 있습니다.

목록을 구성하는 방법은 목록을 사용할 알고리즘과 목록을 생성 할 요소를 가져 오는 순서에 따라 다릅니다.

예를 들어, 사용할 때와 반대 순서로 요소를 가져 오면 a를 사용하고 List앞에 추가 할 수 있습니다 . 꼬리 재귀 함수를 사용하든 foldLeft또는 다른 것을 사용하든 실제로는 관련이 없습니다.

사용하는 것과 동일한 순서로 요소를 가져 ListBuffer오면 성능이 중요하다면 a 가 가장 선호되는 선택입니다.

그러나, 당신은 중요한 경로에없는 및 입력이 충분히 낮은 경우 할 수 있습니다 항상 reverse목록 이상 또는 단지 foldRight또는 reverse선형 시간 입력.

당신은 어떻게 하지 마십시오 할 IS는 사용 List그것과 APPEND를. 이것은 당신에게 단지 앞뒤로 후진하는 것보다 훨씬 더 나쁜 성능을 줄 것입니다.


답변

그리고 간단한 경우 :

val list = List(1,2,3) 

🙂


답변

음 .. 이건 너무 복잡해 보입니다. 제안해도 될까요

def listTestD = (0 to 3).toList

또는

def listTestE = for (i <- (0 to 3).toList) yield i


답변

일반적으로 모든 변수를 제거하여 Scala의 불변성에 초점을 맞추고 싶습니다. 가독성은 여전히 ​​동료에게 중요하므로 :

시험:

scala> val list = for(i <- 1 to 10) yield i
list: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

대부분의 경우 목록으로 변환 할 필요조차 없습니다. 🙂

색인화 된 seq에는 필요한 모든 것이 있습니다.

즉, 이제 해당 IndexedSeq에서 작업 할 수 있습니다.

scala> list.foldLeft(0)(_+_)
res0: Int = 55


답변

저는 항상 List를 선호하고 “for comprehension”전에 “fold / reduce”를 사용합니다. 그러나 중첩 된 “폴드”가 필요한 경우 “for comprehension”이 선호됩니다. “fold / reduce / for”를 사용하여 작업을 수행 할 수없는 경우 재귀는 마지막 수단입니다.

그래서 당신의 예를 들어, 나는 할 것입니다.

((0 to 3) :\ List[Int]())(_ :: _)

내가하기 전에 :

(for (x <- 0 to 3) yield x).toList

참고 : “_”의 순서 때문에 여기에서 “foldLeft (/ :)”대신 “foldRight (: \)”를 사용합니다. StackOverflowException을 발생시키지 않는 버전의 경우 대신 “foldLeft”를 사용하십시오.


답변

사용 List.tabulate과 같이,

List.tabulate(3)( x => 2*x )
res: List(0, 2, 4)

List.tabulate(3)( _ => Math.random )
res: List(0.935455779102479, 0.6004888906328091, 0.3425278797788426)

List.tabulate(3)( _ => (Math.random*10).toInt )
res: List(8, 0, 7)


답변

참고 :이 답변은 이전 버전의 Scala를 위해 작성되었습니다.

Scala 컬렉션 클래스는 Scala 2.8부터 재 설계 될 예정이므로 곧 목록을 만드는 방식을 변경할 준비를하십시오.

목록을 만드는 이전 버전과 호환되는 방법은 무엇입니까? 아직 2.8 문서를 읽지 않았기 때문에 전혀 모르겠습니다.

컬렉션 클래스의 제안 된 변경 사항을 설명하는 PDF 문서