Je suis un novice en langage de programmation fonctionnel et je l’apprends à Scala pour un projet universitaire.
Cela peut sembler simple, mais je ne parviens pas à trouver assez d'aide en ligne pour cela ni pour un moyen simple de procéder. Comment convertir un Array [String] en Array [Double]? J'ai un fichier CSV qui, lorsqu'il est lu dans le REPL, est interprété comme des valeurs de chaîne (chaque ligne du fichier contient un mélange de valeurs d'entier et de chaîne) qui renverrait un type Array [String]. Je veux encoder les valeurs de chaîne avec des valeurs double/int pour renvoyer Array [Double] afin de rendre le tableau homogène. Y at-il un moyen simple de faire cela? Toute orientation sera très appréciée.
Ce que j'ai fait jusqu'à présent c'est:
def retrieveExamplesFromFile(fileName : String) : Array[Array[String]] = {
val items = for {
line <- Source.fromFile(fileName).getLines()
entries = line.split(",")
} yield entries
return items.toArray
}
Le format de chaque ligne (renvoyé sous forme de chaîne []) est le suivant:
[[1.0, 2.0, item1], [5, 8.9, item2],....]
Et pour convertir chaque ligne du fichier CSV en tableau double, je ne dispose que d’une définition psuedo:
def generateNumbersForStringValues(values : Array[String]) : Array[Double] = {
val line = for(item <- values)
{
//correct way?
item.replace("item1", "1.0")
item.replace("item2", "1.0")
}
return //unable to typecast/convert
}
Toutes les idées sont les bienvenues. Merci pour votre temps.
Vous voulez probablement utiliser map
avec toDouble
:
values.map(x => x.toDouble)
Ou plus concement:
values.map(_.toDouble)
Et pour la solution de secours pour les chaînes non doubles, vous pouvez envisager d'utiliser le monad Try
(en scala.util
):
values.map(x => Try(x.toDouble).getOrElse(1.0))
Si vous savez à quoi ressemblera chaque ligne, vous pouvez également rechercher des motifs:
values map {
case Array(a, b, c) => Array(a.toDouble, b.toDouble, 1.0)
}
En développant le commentaire de @ DaunnC, vous pouvez utiliser l'utilitaire Try
pour le faire et appliquer une correspondance de motif au résultat afin d'éviter d'appeler get
ou de placer votre résultat dans un Option
:
import scala.util.{Try, Success, Failure}
def main = {
val maybeDoubles = Array("5", "1.0", "8.5", "10.0", "item1", "item2")
val convertDoubles = maybeDoubles.map { x =>
Try(x.toDouble)
}
val convertedArray = convertDoubles.map {
_ match {
case Success(res) => res
case Failure(f) => 1.0
}
}
convertedArray
}
Cela vous permet de rechercher une correspondance de motif sur le résultat de Try
, qui est toujours soit un Success
ou un Failure
, sans avoir à appeler get
ou à envelopper vos résultats.
Voici quelques informations supplémentaires sur Try, offert par Mauricio Linhares: https://mauricio.github.io/2014/02/17/scala-either-try-and-the-m-W-ord.html
Vous voulez convertir toutes les chaînes avec un repli à 1.0 pour toutes les chaînes non convertibles? Ce serait:
val x = Array(
Array("1.0", "2.0", "item1"),
Array("5", "8.9", "item2"))
x.map( _.map { y =>
try {
y.toDouble
} catch {
case _: NumberFormatException => 1.0
}
})
Scala 2.13
introduit String::toDoubleOption
utilisé dans une transformation map
, peut être associé à Option::getOrElse
pour convertir en toute sécurité String
s en Double
s:
Array("5", "1.0", ".", "8.5", "int").map(_.toDoubleOption.getOrElse(1d))
// Array[Double] = Array(5.0, 1.0, 1.0, 8.5, 1.0)