-1

I have a string 1,3,5-10 and I have to convert this string into a list of integer in scala. The list will like this --->>. List(1,3,5,6,7,8,9,10)

How will be the best way to convert a string list into an integer list using flatMap.

or What will the minimal line of code in Scala to do this.

This is the code I have tried to achieve it but I wanted a better way to do so

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
  }
}

The above code does not use the flat map but can we do this in a better way.

3 Answers3

2

Here is a shortest line of code for Scala 2.13 that for the input sample produces an expected output using 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)

P.S. For error handling (if it is required) you can catch exceptions or use Try which do this underhood.

P.P.S. Code was formatted as a one-liner for easier counting of its length

The Archetypal Paul
  • 41,321
  • 20
  • 104
  • 134
Andriy Plokhotnyuk
  • 7,883
  • 2
  • 44
  • 68
  • 2
    This isn't very safe; it doesn't handle any error cases if the input String is dodgy. – James Whiteley Jan 06 '20 at 17:45
  • 1
    @JamesWhiteley In addition to `Try`, Both negative numbers and non-numeric characters can also be handled by adding extra `case`s. – jrook Jan 06 '20 at 20:05
  • I would just suggest editing this answer and change the style to usual Scala style to improve readability. – jrook Jan 06 '20 at 20:07
  • yes this is good, just define a default case, it will handle other random string. – Hackaholic Jan 06 '20 at 22:45
  • @jrook Scala is both object oriented and functional. its the Style of Scala :) – Hackaholic Jan 06 '20 at 22:47
  • 1
    @Hackaholic, I just meant adhering to basic readability guidelines like [this](https://docs.scala-lang.org/style/indentation.html#line-wrapping) to make the answer more accessible. – jrook Jan 06 '20 at 23:22
  • @Hackaholic being functional or OO has nothing to do with it; this doesn't follow Scala style guidelines. Almost anything can be "short" or a "one-liner" if you replace all new lines with semicolons and delete all unnecessary whitespace until it's condense but hard to read - it might look short and compile, but that doesn't mean it's good code (from a style/standards perspective). – James Whiteley Jan 07 '20 at 10:11
1

Here's somewhere to start:

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()
}

You call inToOut with your String and it either spits out an empty List (if your String is invalid) or a populated List if everything is formatted correctly.

However

This is incomplete.

  • This isn't very condense - you can shorten it considerably, but this code is laid out in a way that is (hopefully) understandable.
  • You'll need to add in more (or different) error handling - your question doesn't specify any sort of error handling, so I've implemented a couple of validations that you could do to get you going but you'll need to decide what the limits of your function are (String format, range rules, ordering, duplicate values, etc).
  • There's probably a quicker way of implementing this without throwing an exception every time something goes wrong. Depends on your implementation; I'll leave this up to you.
  • I haven't accounted for negative numbers (again something for you to implement if you need to).

Anyway, here's an implementation of it working with some success and failure examples: https://scastie.scala-lang.org/FmUsQZQGQIC6X6JRmFLVjg

James Whiteley
  • 3,363
  • 1
  • 19
  • 46
0

I have tried this code and it is working fine for me now.

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
}