Char ou String - > valeur Unicode dans Scala?
Donc je travaille à travers quelques-uns des exercices dans "Scala pour les impatients" et l'un d'eux est:
Écrivez une boucle for
pour calculer le produit des codes Unicode de toutes les lettres d'une chaîne. Par exemple, le produit des caractères dans "Hello" est 9415087488 L.
Le problème suivant est de faire la même chose, mais sans boucle for
- cela suggère que nous devrions vérifier StringOps
dans Scaladoc.
J'ai vérifié la section RichChar
et StringOps
dans Scaladoc, et peut-être que je lis mal ou en regardant dans les mauvais endroits, mais je ne peux pas trouver quoi que ce soit qui me permet de correspondre à leur sortie. J'ai jusqu'à présent essayé:
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
Qui ne correspond pas à leur sortie.
Comment puis-je faire cela, à la fois de la manière for
et non - for
?
Merci!
7 réponses
Lorsque vous faites x.foldLeft(1)(_ * _.toInt)
, le type de résultat sera inférence à un Int
, mais 9415087488 est trop grand pour qu'un Int
le stocke.
Vous devez donc dire à Scala en utilisant Long
pour le stocker.
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
Si vous convertissez chaque RichChar de chaîne .toLong c'est aussi fonctionne. Par exemple, ceci:
str.map (_.toLong).product
- le travail est bien et sans foldLeft ou cycles
C'est une variante cyclique:
def product(str: String): Long = {
var prod: Long = 1
for (ch <- str) prod *= ch
prod
}
Il existe une méthode spéciale "product" dans StringOps qui multiplie les éléments de la collection. Mais il utilise le type Char car la chaîne est constituée d'éléments char. Et nous avons un débordement en essayant de calculer "Bonjour".produit. J'ai donc converti la chaîne en vecteur de longues valeurs Unicode par "Hello".cartographie(_.toLong) et calculé le produit de ses éléments par ce code:
scala> "Hello".map(_.toLong).product
res79: Long = 9415087488
Voici une autre façon:
scala> (for (c <- "Hello") yield c.toLong).product
res36: Long = 9415087488
Le moyen le plus simple que j'ai trouvé pour le faire est:
"Hello".foldLeft(1L)((x:Long, y:Char) => x*y)
La méthode prend deux paramètres: un Long et une fonction déléguée qui prend un long et un Char et renvoie un Long. Vous pouvez passer une fonction anonyme directement comme ceci, ou vous pouvez définir la fonction ailleurs et la transmettre, comme ceci:
def multiply(x:Long, y:Char) = {
x*y
}
"Hello".foldLeft(1L)(multiply)
Je pense que la conversion en carte intermédiaire est inefficace car dans ce cas la collection est itérée deux fois: une fois pour créer une carte de longs et une deuxième fois pour multiplier tous les éléments. La collecte temporaire inutile de Long n'est pas non plus nécessaire. Je donne mon vote à
"Hello".foldLeft(1L)(_ * _)
Une autre variante:
"Hello".aggregate(1L)({(prod,ch) => prod * ch.toLong}, {(p1,p2)=>p1*p2})