120 votes

Le moyen privilégié pour créer une liste Scala

Il y a plusieurs façons de construire une liste immuable en Scala (voir artificiel exemple de code ci-dessous). Vous pouvez utiliser une mutable ListBuffer, créer un var liste et la modifier, utiliser une queue récursive de la méthode, et probablement d'autres que je ne connais pas.

Instinctivement, j'utilise le ListBuffer, mais je n'ai pas de bonne raison de le faire. Est-il préféré ou idiomatiques méthode pour la création d'une liste ou il y a des situations qui sont les meilleurs pour une méthode plutôt qu'une autre?

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

109voto

Daniel C. Sobral Points 159554

ListBuffer est une mutable liste qui a de la constante de temps de l'ajout et de la constante de temps de la conversion en List.

List est immuable et constante de temps de la faire précéder et linéaire en temps ajouter.

Comment vous construisez votre liste dépend de l'algorithme, vous allez utiliser la liste et l'ordre dans lequel vous obtenez des éléments à créer.

Par exemple, si vous obtenez les éléments dans l'ordre inverse de quand ils vont être utilisés, alors vous pouvez simplement utiliser un List et ne la positionne en tête. Si vous allez le faire avec une queue-fonction récursive, foldLeft, ou quelque chose d'autre n'est pas vraiment pertinent.

Si vous obtenez les éléments dans le même ordre que vous les utilisez, puis un ListBuffer est probablement un meilleur choix, si la performance est critique.

Mais, si vous n'êtes pas sur un chemin critique et l'entrée est assez faible, vous pouvez toujours reverse la liste plus tard, ou tout simplement foldRightou reverse l'entrée, qui est linéaire en temps.

Ce que vous NE PAS faire est d'utiliser un List et s'y ajouter. Cela vous donnera beaucoup de moins bonnes performances que juste en ajoutant et en inversant à la fin.

23voto

Alexander Azarov Points 6630

Uhmm.., qui semblent trop complexes pour moi. Puis-je proposer

def listTestD = (0 to 3).toList

ou

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

5voto

JasonG Points 1767

Vous voulez vous concentrer sur l'immuabilité de la Scala généralement en éliminant toutes les vars. La lisibilité est toujours important pour votre prochain donc:

Essayez:

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)

Vous n'avez probablement même pas besoin de se convertir à une liste dans la plupart des cas :)

Le indexé seq aurez tout ce dont vous avez besoin:

Qui est, vous pouvez maintenant travailler sur cette IndexedSeq:

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

2voto

Walter Chang Points 7041

Je préfère toujours la Liste et j'utilise "plier/réduire" avant ", pour la compréhension". Cependant, "la compréhension" est préféré si imbriquée "plis" sont nécessaires. La récursivité est le dernier recours si je ne peux pas accomplir la tâche à l'aide de "plier/réduire/".

donc pour ton exemple, je vais le faire:

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

avant que je n':

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

Remarque: j'utilise "foldRight(:\)" au lieu de "foldLeft(/:)" ici, parce que de l'ordre de"_". Pour une version qui ne jetez pas StackOverflowException, utiliser "foldLeft" à la place.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X