简体   繁体   English

如何使用不同的数据类型拆分要添加到 Scala 中的 Map 的列表

[英]How to split a List to be added to a Map in Scala with Different Data Types

I have some raw test data that I need to split into a map of format:我有一些原始测试数据需要拆分为 map 格式:

Map[String, List[(Int, String, Float)]]地图[字符串,列表[(整数,字符串,浮点数)]]

I have managed to read in the data as a list and will give an example of one line of data below:我已经设法以列表的形式读取数据,并将在下面给出一行数据的示例:

Oor Wullie Route (GCU),1:City Chambers:0.75f,2:Sir Chris Hoy Velodrome:3.8f,3:People's Palace:2.7f,4:Riverside Museum:5.4f,5:Botanic Gardens:2.4f,6:GCU:3.4f

The above represents the following: A Route, a stage number:stage name:total distance of stage以上代表如下:A Route, a stage number:stage name:total distance of stage

So each set of 3 values (ie 1:City Chambers:5) should be added to the [Int, String, Float] section of the map, with the route name being the key.因此,每组 3 个值(即 1:City Chambers:5)应添加到 map 的 [Int, String, Float] 部分,路线名称是关键。

This is my code so far for reading the file and adding it to a list:到目前为止,这是我用于读取文件并将其添加到列表中的代码:

var mapBuffer: Map[String, List[(Int, String, Float)]] = Map()

val fitnessData = "C:\\Users\\josep\\Desktop\\Coursework\\Coursework\\src\\cw.txt"

val lines = Source.fromFile("C:\\Users\\josep\\Desktop\\Coursework\\Coursework\\src\\cw.txt").getLines.toList

I would like to write a funciton for splitting the data up and adding it to a map, essentially doing this:我想编写一个函数来拆分数据并将其添加到 map,基本上是这样做的:

var key ="Oor Wullie Route (GCU)"
var newList = List((1,"City Chambers",0.75f),(2,"Sir Chris Hoy Velodrome",3.8f),(3,"People's Palace",2.7f),(4,"Riverside Museum",5.4f),(5,"Botanic Gardens",2.4f),(6,"GCU",3.4f))
mapBuffer = mapBuffer ++ Map(key -> newList)

How can I add the data to a map in my desired format?如何以我想要的格式将数据添加到 map?

My suggestion would be to use foldLeft.我的建议是使用 foldLeft。 Something like:就像是:

  val resource = Source.fromFile("src/lines.txt")
  val lines = resource.getLines.toList
  resource.close()

  val map = lines.foldLeft(Map[String, List[(Int, String, Float)]]())((map, line) => {
    val keyValuesArray = line.split(",").toList
    val key = keyValuesArray.head
    val listOfValuesAsString = keyValuesArray.tail

    val listOfValues = listOfValuesAsString.map {
      case s"$integer:$string:$float" => (integer.toInt, string, float.toFloat)
    }

    map + (key -> listOfValues)
  })

Start with empty map, and add key->values for each line.从空的 map 开始,为每一行添加 key->values。 Also, try match expressions when you parse data in list (listOfValues part is doing that).此外,在解析列表中的数据时尝试匹配表达式(listOfValues 部分正在这样做)。

This approach is with pattern matching and tail recursion .这种方法是使用pattern matchingtail recursion I think it works very well.我认为它工作得很好。

First I convert the file into a List[Array[String]] .首先,我将文件转换为List[Array[String]]

Second I call loop to go through the list in a recursive way and build the map.其次,我以递归方式通过列表调用 go 循环并构建 map。

Third inside the loop function I call make List to build the list of tuples in a recursive way.循环内的第三个 function 我调用 make List 以递归方式构建元组列表。

As an example:举个例子:

input输入

Oor Wullie Route (GCU),1:City Chambers:0.75f,2:Sir Chris Hoy Velodrome:3.8f,3:People's Palace:2.7f,4:Riverside Museum:5.4f,5:Botanic Gardens:2.4f,6:GCU:3.4f
Oor Wullie Route2 (GCU),1:City Chambers:0.75f,2:Sir Chris Hoy Velodrome:3.8f,3:People's Palace:2.7f,4:Riverside Museum:5.4f,5:Botanic Gardens:2.4f,6:GCU:3.4f
Oor Wullie Route3 (GCU),1:City Chambers:0.75f,2:Sir Chris Hoy Velodrome:3.8f,3:People's Palace:2.7f,4:Riverside Museum:5.4f,5:Botanic Gardens:2.4f,6:GCU:3.4f

code代码

import scala.io.Source

object ConverToMap {

  @annotation.tailrec
  def makeList(lst: List[String], acc: List[(Int, String, Float)]):List[(Int, String, Float)] = {
    lst match {
      case Nil => acc
      case (h :: t) => {
        val data = h.split(":")
        val tuple = (data(0).toInt, data(1), data(2).substring(0,data(2).length - 1 ).toFloat)
        makeList(t, tuple :: acc)
      }
    }
  }

  @annotation.tailrec
  def loop(lst: List[Array[String]], acc:  Map[String, List[(Int, String, Float)]]):  Map[String, List[(Int, String, Float)]] = {
    lst match {
      case Nil => acc
      case (h :: t) => {
        val key = h(0)
        val lTuple = makeList(h.toList.tail, List())
        if(acc.contains(key)) loop(t, acc)
        else loop(t, Map(key -> lTuple) ++ acc)
      }
    }
  }

  def main(args: Array[String]): Unit = {
    val fitnessData = "/home/cloudera/files/tests/to_map.csv"

    val lines = Source.fromFile(fitnessData)
      .getLines
      .toList
      .map(line => line.split(","))

    val mp = loop(lines, Map())

    println(mp)
  }
}

expected result预期结果

Map(Oor Wullie Route3 (GCU) -> List((6,GCU,3.4), (5,Botanic Gardens,2.4), (4,Riverside Museum,5.4), (3,People's Palace,2.7), (2,Sir Chris Hoy Velodrome,3.8), (1,City Chambers,0.7)), 
    Oor Wullie Route2 (GCU) -> List((6,GCU,3.4), (5,Botanic Gardens,2.4), (4,Riverside Museum,5.4), (3,People's Palace,2.7), (2,Sir Chris Hoy Velodrome,3.8), (1,City Chambers,0.7)), 
    Oor Wullie Route (GCU) -> List((6,GCU,3.4), (5,Botanic Gardens,2.4), (4,Riverside Museum,5.4), (3,People's Palace,2.7), (2,Sir Chris Hoy Velodrome,3.8), (1,City Chambers,0.7)))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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