简体   繁体   中英

Convert a String to Map(String, List([Int,Int]))

I am currently learning Scala and I am trying to read lines of text from a file and convert them into a map of type - Map[String, List[(Int,Int)]] , but having difficulty getting there.

Example of text from file = London, -1:19, -2:21, 0:18, -3:24

I want it to be returned as - Map(London -> List((-1,19), (-2,21), (0,18), (-3,24))

I am able to get the city name by doing:

for (line <- Source.fromFile(filename).getLines()) {
        val splitLine = line.split(",").map(_.trim)
        val city = splitLine.head

But I'm not able to get much further after this, I can't split the rest of the values into a list of ints.

EDIT:

Adding the full method in for clarification

def readFile(filename: String): Map[String, List[(Int, Int)]] = {
    val result = for (line <- Source.fromFile(filename).getLines(); array = line.split(",").map(_.trim)) yield Map(array.head -> array.tail.map(x => {
      val y = x.split(":"); (y(0).toInt, y(1).toInt)
    }).toList)
    result
  }

You can do that in one line as

val result = for (line <- Source.fromFile(filename).getLines(); array = line.split(",").map(_.trim)) yield Map(array.head -> array.tail.map(x => {val y = x.split(":"); (y(0).toInt, y(1).toInt)}).toList)

result should be

Map(London -> List((-1,19), (-2,21), (0,18), (-3,24)))
//Iterator[Map[String, (Int, Int}]]

result is an Iterator so you should change the return type accordingly

def readFile(filename: String): Iterator[Map[String, List[(Int, Int)]]] = {
    val result = for (line <- Source.fromFile(filename).getLines(); array = line.split(",").map(_.trim)) yield Map(array.head -> array.tail.map(x => {
      val y = x.split(":"); (y(0).toInt, y(1).toInt)
    }).toList)
    result
  }

Iterators are not really a collection and are not safe so I would suggest you to return list instead as

def readFile(filename: String): List[Map[String, List[(Int, Int)]]] = {
  val result = for (line <- Source.fromFile(filename).getLines(); array = line.split(",").map(_.trim)) yield Map(array.head -> array.tail.map(x => {
    val y = x.split(":"); (y(0).toInt, y(1).toInt)
  }).toList)
  result.toList
}

Your comments suggested that you want

Not really how I would like it displayed as other cities added to the file will give me an output like: List(Map(London -> List((-1,19), (-2,21), (0,18), (-3,24))), Map(Edinburgh -> List((-3,16), (-2, 19), (-1, 21))) etc... instead of Map(London -> List((-1,19), (-2,21), (0,18), (-3,24))), Edinburgh -> List((-3,16), (-2, 19), (-1, 21))) almost like a key/value pair

For that all you need is .flatter.toMap and change the return type to Map[String, List[(Int, Int)]]

def readFile(filename: String): Map[String, List[(Int, Int)]] = {
  val result = for (line <- Source.fromFile(filename).getLines(); array = line.split(",").map(_.trim)) yield Map(array.head -> array.tail.map(x => {
    val y = x.split(":"); (y(0).toInt, y(1).toInt)
  }).toList)
  result.toList.flatten.toMap
}

You can do as follows to get a Map[String,List[(Int, Int)]]] as you requested

for {
 line <- Source.fromFile(filename).getLines()
 val array = line.split(",")
}yield Map(array.head -> array.tail.toList.map(_.split(":").map(_.trim.toInt)).map(elem => (elem(0), elem(1))))

The biggest logic is in the tail management, to turn it to a tuple of Ints

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM