Scala - преобразовать массив [String] в массив [Double]
Я новичок в функциональном языке программирования, и я изучаю его в Scala для университетского проекта.
Это может показаться простым, но я не могу найти достаточную помощь в Интернете для этого или простого способа сделать это - как я могу преобразовать Array [String] в Array [Double]? У меня есть файл CSV, который при чтении в REPL интерпретируется как значения String (каждая строка файла содержит сочетание целых и строковых значений), которые возвращают тип Array [String]. Я хочу кодировать строковые значения с помощью значений double/int, чтобы вернуть Array [Double], чтобы сделать массив однородным. Есть ли простой способ сделать это? Любые рекомендации будут высоко оценены.
Что я сделал до сих пор:
def retrieveExamplesFromFile(fileName : String) : Array[Array[String]] = {
val items = for {
line <- Source.fromFile(fileName).getLines()
entries = line.split(",")
} yield entries
return items.toArray
}
Формат каждой строки (возвращаемый как String []):
[[1.0, 2.0, item1], [5, 8.9, item2],....]
И чтобы преобразовать каждую строку в CSV файл в двойной массив, у меня есть только определение 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
}
Любые идеи приветствуются. Спасибо за ваше время.
Ответы
Ответ 1
Вероятно, вы хотите использовать map
вместе с toDouble
:
values.map(x => x.toDouble)
Или более кратко:
values.map(_.toDouble)
И для возврата для недвойных строк вы можете использовать монаду Try
(в scala.util
):
values.map(x => Try(x.toDouble).getOrElse(1.0))
Если вы знаете, как будет выглядеть каждая строка, вы также можете выполнить сопоставление с образцом:
values map {
case Array(a, b, c) => Array(a.toDouble, b.toDouble, 1.0)
}
Ответ 2
Вы хотите преобразовать все строки в double с резервными значениями в 1.0 для всех необратимых строк? Это будет:
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
}
})
Ответ 3
Развернув комментарий @DaunnC, вы можете использовать утилиту Try
, чтобы сделать это, и совпадение шаблонов в результате, чтобы избежать вызова get
или переноса результата в 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
}
Это позволяет сопоставлять шаблон по результату Try
, который всегда является либо Success
, либо Failure
, без необходимости называть get
или иначе обертывать ваши результаты.
Ниже приведена дополнительная информация о Try любезно предоставлена Маурисио Линаресом: https://mauricio.github.io/2014/02/17/scala-either-try-and-the-m-word.html
Ответ 4
Scala 2.13
представляет String::toDoubleOption
который используется в преобразовании map
, может быть связан с Option::getOrElse
для безопасного приведения String
в 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)