Ahora que ha editado para hacer una pregunta casi completamente diferente, le daré una respuesta diferente. En lugar de apuntar a un tutorial sobre mapas y pliegues, solo daré uno.
En Scala, primero necesita saber cómo crear una función anónima. Va como así, de más general a más específico:
(var1: Type1, var2: Type2, ..., varN: TypeN) => /* output */
(var1, var2, ..., varN) => /* output, if types can be inferred */
var1 => /* output, if type can be inferred and N=1 */
Éstos son algunos ejemplos:
(x: Double, y: Double, z: Double) => Math.sqrt(x*x + y*y + z*z)
val f:(Double,Double)=>Double = (x,y) => x*y + Math.exp(-x*y)
val neg:Double=>Double = x => -x
Ahora, el método de listas map
y tal será aplicar una función (anónimo o no) cada elemento del mapa. Es decir, si usted tiene
List(a1,a2,...,aN)
f:A => B
continuación
List(a1,a2,...,aN) map (f)
produce
List(f(a1) , f(a2) , ..., f(aN))
Hay todo tipo de razones por qué esto podría ser de utilidad. Tal vez tengas un montón de cadenas y quieras saber cuánto tiempo tiene cada una, o si quieres convertirlas en mayúsculas o si quieres que estén hacia atrás. Si usted tiene una función que hace lo que quiere un elemento, un mapa lo hará a todos los elementos:
scala> List("How","long","are","we?") map (s => s.length)
res0: List[Int] = List(3, 4, 3, 3)
scala> List("How","capitalized","are","we?") map (s => s.toUpperCase)
res1: List[java.lang.String] = List(HOW, CAPITALIZED, ARE, WE?)
scala> List("How","backwards","are","we?") map (s => s.reverse)
res2: List[scala.runtime.RichString] = List(woH, sdrawkcab, era, ?ew)
Entonces, eso es un mapa en general, y en Scala.
¿Pero y si queremos recoger nuestros resultados? Ahí es donde entra el doblez (foldLeft
siendo la versión que comienza a la izquierda y funciona bien).
Supongamos que tenemos una función f:(B,A) => B
, es decir, toma una B y una A, y las combina para producir una B. Bueno, podríamos comenzar con una B y luego incluir nuestra lista de A en una en un tiempo, y al final de todo, tendríamos un poco de B. Eso es exactamente lo que hace fold. foldLeft
lo hace comenzando desde el extremo izquierdo de la lista; foldRight
comienza desde la derecha. Es decir,
List(a1,a2,...,aN) foldLeft(b0)(f)
produce
f(f(... f(f(b0,a1) , a2) ...), aN)
donde b0
es, por supuesto, su valor inicial.
Entonces, tal vez tengamos una función que toma un int y una cadena, y devuelve el int o la longitud de la cadena, cualquiera que sea mayor - si doblamos nuestra lista usando eso, nos dirá la cadena más larga (suponiendo que comencemos con 0). O podríamos agregar la longitud al int, acumulando valores a medida que avanzamos.
Démosle una oportunidad.
scala> List("How","long","is","longest?").foldLeft(0)((i,s) => i max s.length)
res3: Int = 8
scala> List("How","long","is","everyone?").foldLeft(0)((i,s) => i + s.length)
res4: Int = 18
Bueno, está bien, pero lo que si queremos conocer que es el más largo? Una forma (tal vez no la mejor, pero ilustra bien un patrón útil) es llevar tanto la longitud (un número entero) y el contendiente principal (una cadena).Vamos a dar una que ir:
scala> List("Who","is","longest?").foldLeft((0,""))((i,s) =>
| if (i._1 < s.length) (s.length,s)
| else i
|)
res5: (Int, java.lang.String) = (8,longest?)
Aquí, i
es ahora una tupla de tipo (Int,String)
, y i._1
es la primera parte de esa tupla (un Int).
Pero en algunos casos como este, usar un doblez no es realmente lo que queremos. Si queremos el más largo de dos cadenas, la función más natural sería una como max:(String,String)=>String
. ¿Cómo aplicamos eso?
Bueno, en este caso, hay un caso predeterminado "más corto", por lo que podríamos plegar la función string-max comenzando con "". Pero una mejor manera es usar reducir. Al igual que con fold, hay dos versiones, una que funciona desde la izquierda, la otra que funciona desde la derecha. No requiere valor inicial, y requiere una función f:(A,A)=>A
. Es decir, toma dos cosas y devuelve una del mismo tipo. Aquí hay un ejemplo con una función de cadena máxima:
scala> List("Who","is","longest?").reduceLeft((s1,s2) =>
| if (s2.length > s1.length) s2
| else s1
|)
res6: java.lang.String = longest?
Ahora, hay solo dos trucos más. En primer lugar, los dos siguientes significan lo mismo:
list.foldLeft(b0)(f)
(b0 /: list)(f)
Note como el segundo es más corto, y que tipo de le da la impresión de que usted está tomando b0
y hacer algo a la lista con él (el que está) (:\
es lo mismo que foldRight
, pero que lo utilice de esta manera: (list :\ b0) (f)
En segundo lugar, si sólo se refieren a una variable de una vez, puede utilizar _
en lugar del nombre de la variable y omitir la parte x =>
de la declaración de la función anónima . He aquí dos ejemplos:.
scala> List("How","long","are","we?") map (_.length)
res7: List[Int] = List(3, 4, 3, 3)
scala> (0 /: List("How","long","are","we","all?"))(_ + _.length)
res8: Int = 16
en este punto, usted debe ser capaz de crear funciones y mapa, pliegue, y reducirlos usando Scala Por lo tanto, si usted sabe cómo su algoritmo debe trabajar, debe ser razonablemente fácil de implementar.
Estás en el s ame como Tom? Consulte http://stackoverflow.com/questions/2274852/scala-how-to-perform-pattern-matching-with-vararg-case-classes. – huynhjl
Esta no es una pregunta acerca de Scala y 'foldLeft'. Esta es una pregunta sobre algoritmos. Sería mejor que preguntaras: "¿Cómo calculo el cuadro delimitador más pequeño de una lista de formas, usando estructuras de datos inmutables?" _. Etiquete la pregunta como agnóstica del lenguaje y algoritmos. Y tal vez programación funcional. Si tiene problemas para implementar los algoritmos sugeridos en Scala, abre una pregunta de Scala al respecto. La presente pregunta se dirige al grupo equivocado. –