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!

27
demandé sur adelbertc 2012-06-23 04:07:56

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
28
répondu Brian Hsu 2012-06-23 16:48:55

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
}
13
répondu seth2810 2013-03-20 05:40:52

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
7
répondu Andrey Kudryavtsev 2015-09-15 11:55:48

Voici une autre façon:

scala> (for (c <- "Hello") yield c.toLong).product
res36: Long = 9415087488
5
répondu Rihad 2015-03-02 18:31:13

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)
3
répondu emote_control 2014-04-08 02:34:25

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)(_ * _)
2
répondu Andris 2016-02-10 08:17:48

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

0
répondu jcadcell 2016-06-15 17:28:10