Как преобразовать строку в список целых чисел в Scala - PullRequest
0 голосов
/ 06 января 2020

У меня есть строка 1,3,5-10, и мне нужно преобразовать эту строку в список целых чисел в scala. Список понравится --- >>. List(1,3,5,6,7,8,9,10)

Как будет наилучшим способом преобразовать список строк в целочисленный список, используя flatMap.

или Что будет минимальной строкой кода в Scala для этого.

Это код, который я пытался сделать, но я хотел получить лучший способ сделать это

val selectedNumberList: mutable.MutableList[Int] = mutable.MutableList[Int]()
val numbersList = "1,3,5-10".split(",").toList
for(i <- 0 until numbersList.size ){
if(numbersList(i).contains("-")){
val splitNumberToList = numbersList(i).split("-").toList
    for(j <- splitNumberToList.head.toInt to splitNumberToList.last.toInt){
      selectedNumberList += j
    }
}else{
    selectedNumberList += numbersList(i).toInt
  }
}

Приведенный выше код не использует плоскую карту но можем ли мы сделать это лучше?

Ответы [ 3 ]

2 голосов
/ 06 января 2020

Вот самая короткая строка кода для Scala 2.13, которая для входного образца дает ожидаемый результат, используя flatMap:

scala> "1,3,5-10".split(',')
                 .toList
                 .flatMap{case s"$a-$b" => a.toInt to b.toInt;
                          case a        => a.toInt::Nil}
res0: List[Int] = List(1, 3, 5, 6, 7, 8, 9, 10)

PS Для обработки ошибок (если это требуется) вы можете поймать исключения или использовать Try, которые делают это ниже.

Код PPS был отформатирован как однострочный для более легкого подсчета его длины

1 голос
/ 06 января 2020

Вот с чего начать:

import scala.util.Try

def validateRegex(input: String): Try[Unit] = Try(if(!input.matches("((\\d+-\\d+|\\d+)($|,(\\s+)?))+")) throw new Exception(""))
def validateRange(input: String): Try[Unit] = Try {
  val pattern = "\\d+-\\d+".r
  (pattern findAllIn input).toList.map(_.split("-").map(_.toInt)).map(_.toList).map {
    case a :: b :: Nil if a >= b => throw new Exception("")
    case _ =>
  }
}

def validateInput(input: String): Boolean = {
  val list: List[Try[Unit]] = List(
    validateRegex(input),
    validateRange(input)
  )
  !list.exists(_.isFailure)
}

def inToOut(input: String): List[Int] = {
  if(validateInput(input)) input.split(",\\s?").flatMap {
    case r if r.contains("-") =>
      val s = r.split("-").map(_.toInt)
      (s(0) to s(1)).toList
    case i => List(i.toInt)
  }.toList else List()
}

Вы вызываете inToOut со своей строкой, и она либо выплевывает пустой список (если ваша строка недопустима), либо заполненный список, если все отформатировано правильно.

Однако

Это неполно.

  • Это не очень сжато - вы можете значительно сократить его, но этот код изложен таким образом, что (надеюсь) понятно.
  • Вам нужно будет добавить более (или другую) обработку ошибок - ваш вопрос не определяет какую-либо обработку ошибок, поэтому я реализовал несколько проверок, которые вы может сделать, чтобы вы начали, но вам нужно решить, каковы ограничения вашей функции (формат строки, правила диапазона, порядок, повторяющиеся значения и т. Д. c).
  • Есть возможно, это более быстрый способ реализовать это без исключения каждый раз, когда что-то идет не так. Зависит от вашей реализации; Я оставлю это на ваше усмотрение.
  • Я не учел отрицательные числа (опять же, что-то для вас, чтобы реализовать, если вам нужно).

В любом случае, Вот его реализация с некоторыми примерами успеха и неудач: https://scastie.scala-lang.org/FmUsQZQGQIC6X6JRmFLVjg

0 голосов
/ 07 января 2020

Я попробовал этот код, и теперь он работает нормально для меня.

val numbers = "1,3,5-10".split(",").toList.flatMap{
  case x if x.contains("-") =>
    val k = x.split("-")
    k.head.toInt to k(1).toInt
  case a => a.toInt::Nil
}
...