0

I am using Scala and reading input from the console. I am able to regurgitate the strings that make up each line, but if my input has the following format, how can I access each integer within each line?

2 2 1 2 2 2 1 1 

Currently I just regurgitate the input back to the console using

object Main { def main(args: Array[String]): Unit = { for (ln <- io.Source.stdin.getLines) println(ln) //how can I access each individual number within each line? } } 

And I need to compile this project like so:

$ scalac main.scala

$ scala Main <input01.txt 2 2 1 2 2 2 1 1 
1
  • 1
    Do you need one list of integers, or a list of lists of integers? Commented Jul 28, 2020 at 16:08

2 Answers 2

2

A reasonable algorithm would be:

  • for each line, split it into words
  • parse each word into an Int

An implementation of that algorithm:

io.Source.stdin.getLines // for each line... .flatMap( _.split("""\s+""") // split it into words .map(_.toInt) // parse each word into an Int ) 

The result of this expression will be an Iterator[Int]; if you want a Seq, you can call toSeq on that Iterator (if there's a reasonable chance there will be more than 7 or so integers, it's probably worth calling toVector instead). It will blow up with a NumberFormatException if there's a word which isn't an integer. You can handle this a few different ways... if you want to ignore words that aren't integers, you can:

import scala.util.Try io.Source.stdin.getLines .flatMap( _.split("""\s+""") .flatMap(Try(_.toInt).toOption) ) 
Sign up to request clarification or add additional context in comments.

7 Comments

Why toVector? But in any case, +1 to not using Seqs but rather any concrete collection (I would just go with List). - in 2.13 you can use toIntOption instead of Try(_.toInt).toOption
Beyond about 7 elements (it will vary from one JVM and underlying architecture to another), Vector becomes far more memory-efficient than List, while having basically the same performance for map/flatMap/filter and friends (which is often all you want from any collection). Prepending and head/tail decomposition are the only reasons IMO to use a LinearSeq over an IndexedSeq.
I doubt it, I am pretty sure a List is actually more memory and CPU efficient than Vector in most cases. The only reason for using an IndexedSeq* would be if you need fast access by index (which is weird in functional code) and in such cases an ArraySeq is better than a Vector.
List by definition creates a new object for every element (about 30 or so bytes per element). Vector creates a new array of size 32 for every 32 (or portion thereof elements) so about 200 bytes for the first 32 elements.
Oh so I must have misunderstood Martin's explanation in the Coursera course, or things changed. In any case, that post is quite old, it uses Scala 2.11 many changed about collections in 2.13, so it's not that relevant anymore. Anyways, again, agree to disagree as Li said, just pick one and continue with your life. I just have found List to be more useful in most cases and ArraySeq to be a better replacement of Vector.
|
-1

The following will give you a flat list of numbers.

val integers = ( for { line <- io.Source.stdin.getLines number <- line.split("""\s+""").map(_.toInt) } yield number ) 

As you can read here, some care must be taken when parsing the numbers.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.