2012-06-23 4 views
27

So in „für die Ungeduldig Scala“ ein paar der Übungen durch ich arbeite und einer von ihnen ist:Char oder String -> Unicode-Wert in Scala?

eine for Schleife schreibt das Produkt der Unicode-Codes aller Buchstaben in einer Zeichenfolge für die Berechnung. Zum Beispiel ist das Produkt der Zeichen in "Hello" 9415087488 L.

Das nächste Problem besteht darin, das gleiche zu tun, aber ohne eine for Schleife - es deutet darauf hin, dass wir StringOps in Scaladoc überprüfen sollten.

Ich überprüfte die RichChar und StringOps Abschnitt in Scaladoc, und vielleicht bin ich falsch lesen oder an den falschen Stellen suchen, aber ich kann nichts finden, das mich ihre Ausgabe übereinstimmen. Ich habe es bisher versucht:

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 

Welche nicht ihre Ausgabe übereinstimmt.

Wie mache ich das, sowohl in der for und nicht for Weise?

Danke!

+0

Es gibt einen anderen Weg, wenn man es in zwei Schritten tun. Hinweis: Die letzte der beiden Methoden hat nur einen impliziten Parameter. –

Antwort

26

Wenn Sie x.foldLeft(1)(_ * _.toInt) tun, wird der Ergebnistyp auf Int rückschließen, aber 9415087488 ist zu groß für eine Int, um es zu speichern.

Also müssen Sie Scala mit zu speichern, um es zu speichern.

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 hat es. Vielen Dank! – adelbertc

+5

Danke von mir auch. Seltsamerweise wird in der gerade heruntergeladenen pdf-Version der falsche Wert angegeben (825152896). – Markus

+0

seltsam, aber mit "für (fi <-" Hallo ") i * = fi.toChar" Ich habe den gleichen Wert wie in Buch. Hmmm. –

12

Wenn Sie jeden RichChar von String .toLong konvertieren, funktioniert es auch. Zum Beispiel dieser:

str.map (_.toLong).product - Arbeit ist in Ordnung und ohne foldLeft oder Zyklen

Dies ist zyklische Variante:

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

Die einfachste Art, wie ich gefunden habe, dies zu tun ist:

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

Die Methode akzeptiert zwei Parameter: eine Long- und eine Delegate-Funktion, die Long und Char akzeptiert und eine Long zurückgibt. Sie können eine anonyme Funktion in direkt wie diese passieren, oder Sie können die Funktion an anderer Stelle definieren und geben es in, etwa so:

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

Hier ist eine andere Art und Weise:

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

Es gibt einen speziellen „Produkt“ Methode in StringOps, die die Elemente der Auflistung multipliziert. Aber es verwendet Char-Typ, da die Zeichenfolge aus Zeichenelementen besteht. Und wir haben einen Überlauf beim Versuch, "Hello" .product zu berechnen. So konvertiert ich die Zeichenfolge Vektor von Long Unicode-Werte von „Hallo“ .map (_ Tolong.) Und berechnet das Produkt ihrer Elemente durch diesen Code:

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

Danke! Ich vermutete auch einen Überlauf. Aber war nicht sicher, wie man es anfordert, es einem Long zuzuordnen. – asgs

+0

Die for-Schleife in Rihads Antwort und die Karte in dieser Antwort sind Notationsvarianten. Der Compiler konvertiert die for-Schleife in eine Karte, glaube ich. Es ist eine Frage des Geschmacks, die Sie verwenden. – airfoyle

2

ich die Umstellung auf Zwischen Karte denken würde, ist Ineffizient, da in diesem Fall die Sammlung zweimal durchlaufen wird: einmal zum Erstellen einer Karte von Longs und zum zweiten Mal zum Multiplizieren aller Elemente. Unnötige temporäre Sammlung von Long ist auch nicht erforderlich.Ich gebe meine Stimme

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

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