2012-06-23 15 views
27

Così sto lavorando attraverso alcuni degli esercizi di "Scala per l'Impaziente" e uno di loro è:Char o String -> Valore Unicode in Scala?

scrivere un ciclo for per calcolare il prodotto dei codici Unicode di tutte le lettere in una stringa. Ad esempio, il prodotto dei caratteri in "Hello" è 9415087488 L.

Il prossimo problema è quello di fare lo stesso, ma senza un ciclo for - si suggerisce di controllare StringOps in Scaladoc.

Ho controllato la sezione RichChar e StringOps in Scaladoc, e forse sto fraintendendo o sto cercando nei posti sbagliati, ma non riesco a trovare nulla che possa farmi corrispondere al loro output. Ho finora provato:

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 

Che non corrisponde alla loro uscita.

Come si esegue questa operazione, in entrambi i modi for e non for?

Grazie!

+0

C'è un altro modo, se lo si fa in due fasi. Suggerimento: l'ultimo dei due metodi ha solo un parametro implicito. –

risposta

26

Quando si esegue x.foldLeft(1)(_ * _.toInt), il tipo di risultato sarà dedotto da un Int, ma 9415087488 è troppo grande per un Int per memorizzarlo.

Quindi devi dire a Scala che usa Long per memorizzarlo.

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 capito. Grazie! – adelbertc

+5

Grazie anche da parte mia. Stranamente, nella versione pdf che ho appena scaricato, viene fornito il valore errato (825152896). – Markus

+0

strano, ma con "per (fi <-" Ciao ") i * = fi.toChar" Ho lo stesso valore del libro. Hmmm. –

12

Se si converte ogni RichChar di String .toLong funziona anche. Ad esempio, questo:

str.map (_.toLong).product - di lavorare bene e senza foldLeft o cicli

Questa è la variante ciclica:

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

Il modo più semplice che ho trovato per fare questo è:

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

Il metodo accetta due parametri: una funzione Long e una delegate che richiede Long e Char e restituisce Long. È possibile passare una funzione anonima in diretta come questo, o è possibile definire la funzione altrove e passarlo in, in questo modo:

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

Ecco un altro modo:

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

C'è un "prodotto" speciale metodo in StringOps che moltiplica gli elementi della collezione. Ma usa il tipo Char perché la stringa è composta da elementi char. E stiamo avendo overflow mentre proviamo a calcolare "Hello" .product. Così ho convertito la stringa da vettore di valori lungo Unicode da "Ciao" .map (_ Tolong.) E calcolato il prodotto dei suoi elementi da questo codice:

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

Grazie! Sospettavo anche un trabocco. Ma non era sicuro di chiederlo per mapparlo a Long. – asgs

+0

Il ciclo for nella risposta di Rihad e la mappa in questa risposta sono varianti notazionali. Il compilatore converte il ciclo for in una mappa, credo. È una questione di gusti che usi. – airfoyle

2

penserei la conversione alla mappa intermedio è inefficiente perché in questo caso la raccolta viene iterata due volte: una volta per creare una mappa di long e una seconda volta per moltiplicare tutti gli elementi. La raccolta temporanea non necessaria di Long's non è necessaria.Io do il mio voto a

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

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