2012-06-23 10 views
27

así que estoy trabajando a través de algunos de los ejercicios de "Scala para impacientes" y uno de ellos es:Char o cadena -> Valor Unicode en Scala?

escribe un bucle for para calcular el producto de los códigos Unicode de todas las letras de una cadena. Por ejemplo, el producto de los caracteres en "Hola" es 9415087488 L.

El siguiente problema es hacer lo mismo, pero sin un bucle for - insinúa que debemos verificar StringOps en Scaladoc.

Comprobé la sección RichChar y StringOps en Scaladoc, y tal vez estoy malinterpretando o buscando en lugares incorrectos, pero no encuentro nada que me permita hacer coincidir sus resultados. Hasta ahora he intentado:

scala> x.foldLeft(1)(_ * _.toInt) 
res0: Int = 825152896 

scala> x.foldLeft(1)(_ * _.getNumericValue) 
res5: Int = 2518992 

scala> x.foldLeft(1)(_ * _.intValue()) 
res6: Int = 825152896 

scala> var x = 1 
x: Int = 1 

scala> for (c <- "Hello") x *= c.toInt 

scala> x 
res12: Int = 825152896 

que no coincide con su salida.

¿Cómo hago esto, tanto en el for como en el no for?

Gracias!

+0

Hay otra manera, si lo hace en dos pasos. Sugerencia: el último de los dos métodos solo tiene un parámetro implícito. –

Respuesta

26

Cuando lo haga x.foldLeft(1)(_ * _.toInt), el tipo de resultado se deduce a un Int, pero 9415087488 es demasiado grande para un Int para almacenarlo.

Así que debes decirle a Scala usando Long para almacenarlo.

scala> val x = "Hello" 
x: java.lang.String = Hello 

scala> x.foldLeft(1L)(_ * _.toInt) 
res1: Long = 9415087488 

scala> var x: Long = 1 
x: Long = 1 

scala> for (c <- "Hello") x *= c.toInt 

scala> x 
res7: Long = 9415087488 
+0

Ahhh lo tengo. ¡Gracias! – adelbertc

+5

Gracias de mí también. Curiosamente, en la versión pdf que acabo de descargar, se da el valor incorrecto (825152896). – Markus

+0

extraño, pero con "para (fi <-" Hola ") i * = fi.toChar" Tengo el mismo valor que en el libro. Hmmm. –

12

Si convierte cada RichChar de String .toLong también funciona. Por ejemplo, esto:

str.map (_.toLong).product - de trabajo fino y sin foldLeft o ciclos

Ésta es la variante cíclica:

def product(str: String): Long = { 
    var prod: Long = 1 
    for (ch <- str) prod *= ch 
    prod 
} 
3

La forma más sencilla que he encontrado para hacer esto es:

"Hello".foldLeft(1L)((x:Long, y:Char) => x*y) 

El método toma dos parámetros: un Largo y una función de delegado que toma un Largo y un Char y devuelve un Largo. Se puede pasar una función anónima directamente como este, o puede definir la función en otro lugar y pasarlo en, así:

def multiply(x:Long, y:Char) = { 
    x*y 
} 
"Hello".foldLeft(1L)(multiply) 
4

Ésta es otra manera:

scala> (for (c <- "Hello") yield c.toLong).product 
res36: Long = 9415087488 
6

Hay un "producto" especial método en StringOps que multiplica los elementos de la colección. Pero usa el tipo Char porque la cadena consta de elementos char. Y estamos teniendo desbordamiento al intentar calcular el producto "Hello". Así que me convertí a la cadena del vector de valores a largo Unicode "Hola" .map (_ Tolong.) Y se calcula el producto de sus elementos por este código:

scala> "Hello".map(_.toLong).product 
res79: Long = 9415087488 
+0

¡Gracias! Sospeché un desbordamiento también. Pero no estaba seguro de cómo pedirle que lo asigne a Long. – asgs

+0

El bucle for en la respuesta de Rihad y el mapa en esta respuesta son variantes de notación. El compilador convierte el bucle for a un mapa, creo. Es una cuestión de gusto que utilizas. – airfoyle

2

pensaría que la conversión al mapa intermedio es ineficaz porque en este caso la colección se itera dos veces: una para crear un mapa de longitudes y una segunda para multiplicar todos los elementos. La colección temporal innecesaria de Long tampoco es necesaria.Doy mi voto a

"Hello".foldLeft(1L)(_ * _) 
0

Otra variante: "Hello".aggregate(1L)({(prod,ch) => prod * ch.toLong}, {(p1,p2)=>p1*p2})

Cuestiones relacionadas