tutorial software renault fungicida examples constructora blanquerna scala

software - scala tutorial



Forma preferida de crear una lista de Scala (9)

Como nuevo desarrollador de scala, escribí una pequeña prueba para verificar el tiempo de creación de la lista con los métodos sugeridos anteriormente. Parece que (para (p <- (0 a x)) rinda p) para enumerar el enfoque más rápido.

import java.util.Date object Listbm { final val listSize = 1048576 final val iterationCounts = 5 def getCurrentTime: BigInt = (new Date) getTime def createList[T] ( f : Int => T )( size : Int ): T = f ( size ) // returns function time execution def experiment[T] ( f : Int => T ) ( iterations: Int ) ( size :Int ) : Int = { val start_time = getCurrentTime for ( p <- 0 to iterations ) createList ( f ) ( size ) return (getCurrentTime - start_time) toInt } def printResult ( f: => Int ) : Unit = println ( "execution time " + f ) def main( args : Array[String] ) { args(0) match { case "for" => printResult ( experiment ( x => (for ( p <- ( 0 to x ) ) yield p) toList ) ( iterationCounts ) ( listSize ) ) case "range" => printResult ( experiment ( x => ( 0 to x ) toList ) ( iterationCounts ) ( listSize ) ) case "::" => printResult ( experiment ( x => ((0 to x) :/ List[Int]())(_ :: _) ) ( iterationCounts ) ( listSize ) ) case _ => println ( "please use: for, range or ::/n") } } }

Hay varias maneras de construir una lista inmutable en Scala (consulte el código de ejemplo artificial a continuación). Puedes usar un ListBuffer mutable, crear una lista var y modificarla, usar un método recursivo de cola y probablemente otros que no conozca.

Instintivamente, uso el ListBuffer, pero no tengo una buena razón para hacerlo. ¿Existe un método preferido o idiomático para crear una lista, o hay situaciones que son mejores para un método que para otro?

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


Desea centrarse en la inmutabilidad en Scala en general mediante la eliminación de cualquier vars. La legibilidad sigue siendo importante para su prójimo, así que:

Tratar:

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)

Probablemente ni siquiera necesite convertir a una lista en la mayoría de los casos :)

El seq indexado tendrá todo lo que necesita:

Es decir, ahora puede trabajar en IndexedSeq:

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


Siempre prefiero List y uso "fold / reduce" antes de "para comprensión". Sin embargo, se prefiere "para la comprensión" si se requieren "pliegues" anidados. La recursividad es el último recurso si no puedo lograr la tarea usando "fold / reduce / for".

entonces para su ejemplo, lo haré:

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

antes que yo:

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

Nota: utilizo "foldRight (: /)" en lugar de "foldLeft (/ :)" aquí debido al orden de "_" s. Para una versión que no arroja Exception, use "foldLeft" en su lugar.


Uhmm ... me parecen demasiado complejos. ¿Puedo proponer?

def listTestD = (0 to 3).toList

o

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


Usando List.tabulate , así,

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)


Y para casos simples:

val list = List(1,2,3)

:)


solo un ejemplo que usa collection.breakOut

scala> val a : List[Int] = (for( x <- 1 to 10 ) yield x * 3)(collection.breakOut) a: List[Int] = List(3, 6, 9, 12, 15, 18, 21, 24, 27, 30) scala> val b : List[Int] = (1 to 10).map(_ * 3)(collection.breakOut) b: List[Int] = List(3, 6, 9, 12, 15, 18, 21, 24, 27, 30)


ListBuffer es una lista mutable que tiene un ListBuffer de tiempo constante y una conversión de tiempo constante en una List .

List es inmutable y tiene un prepend de tiempo constante y un apendido de tiempo lineal.

La forma en que construyas tu lista depende del algoritmo para el que usarás la lista y del orden en el que obtienes los elementos para crearla.

Por ejemplo, si obtienes los elementos en el orden opuesto de cuándo van a usarse, entonces puedes simplemente usar una List y hacerlos antes. Ya sea que lo haga con una función recursiva de cola, foldLeft u otra cosa no es realmente relevante.

Si obtienes los elementos en el mismo orden en que los usas, entonces es más probable que un ListBuffer sea ​​una opción preferible, si el rendimiento es crítico.

Pero, si no está en una ruta crítica y la entrada es lo suficientemente baja, siempre puede reverse la lista más tarde, o simplemente foldRight , o reverse la entrada, que es de tiempo lineal.

Lo que NO HACE es usar una List y anexarla. Esto le proporcionará un rendimiento mucho peor que el de adelantarse y retroceder al final.


Nota: esta respuesta está escrita para una versión anterior de Scala.

Las clases de la colección Scala se rediseñarán a partir de Scala 2.8, así que prepárese para cambiar la forma de crear listas muy pronto.

¿Cuál es la forma de crear una lista compatible con versiones anteriores? No tengo idea ya que aún no he leído los 2.8 documentos.

Un documento PDF que describe los cambios propuestos de las clases de colección