【问题标题】:How to split a List to be added to a Map in Scala如何在Scala中拆分要添加到地图的列表
【发布时间】:2019-08-29 10:52:47
【问题描述】:

我有一些原始测试数据需要拆分为格式图:

Map[String, List[(Int, Int, Int)]]

我已经设法以列表的形式读入数据,并将在下面给出一行数据的示例:

Mon-18-June-2018,1:10:5,2:20:10,3:30:15,4:40:20,5:50:25

以上表示如下:一个日期,该日期的一个时间段:步行时间:以较高速度步行所花费的时间

因此应将每组 3 个值(即 1:10:5)添加到地图的 [Int, Int, Int] 部分,其中日期是关键。

这是我目前用于读取文件并将其添加到列表的代码:

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

    val fitnessData = "C:\\Users\\ritch\\IdeaProjects\\Coursework\\src\\data.txt"

    val lines = Source.fromFile("C:\\Users\\ritch\\IdeaProjects\\Coursework\\src\\data.txt").getLines.toList

我想编写一个函数来拆分数据并将其添加到地图中,基本上是这样做的:

var key ="Mon-18-June-2018"
var newList = List((1,10,5),(2,20,10),(3,30,15),(4,40,20),(5,50,25))
mapBuffer = mapBuffer ++ Map(key -> newList)

如何将数据添加到所需格式的地图中?

【问题讨论】:

    标签: scala list dictionary functional-programming


    【解决方案1】:

    以下实现是一个通用的实现,不依赖于您在运行时获得的参数数量。

    val line = "Mon-18-June-2018,1:10:5,2:20:10,3:30:15,4:40:20,5:50:25"
    val arr = line.split(",")
    
    val map = scala.collection.mutable.Map[String,List[List[Int]]]()
    val key = arr(0)
    val values = arr.toList.drop(1).map{
      case str : String =>
        str.split(":").map(_.toInt).foldLeft(List[Int]())(
          (acc,res) =>
            acc :+ res
        )
    }
    
    map += (key -> values)
    

    这会给你一个输出

    res0: scala.collection.mutable.Map[String,List[List[Int]]] = Map(Mon-18-June-2018 -> List(List(1, 10, 5), List(2, 20, 10), List(3, 30, 15), List(4, 40, 20), List(5, 50, 25)))
    

    但是,如果您确定始终会以 1:10:2 的格式获取参数,那么您可以立即使用元组实现而不是折叠列表。

    val line = "Mon-18-June-2018,1:10:5,2:20:10,3:30:15,4:40:20,5:50:25"
    val arr = line.split(",")
    
    val map = scala.collection.mutable.Map[String,List[(Int,Int,Int)]]()
    val key = arr(0)
    val values = arr.toList.drop(1).map{
      case str : String =>
        str.split(":").map(_.toInt).foldLeft(List[Int]())(
          (acc,res) =>
            acc :+ res
        )
    }.map(x => (x(0),x(1),x(2)))
    
    map += (key -> values)
    

    这会获取一个输出为

    res0: scala.collection.mutable.Map[String,List[(Int, Int, Int)]] = Map(Mon-18-June-2018 -> List((1,10,5), (2,20,10), (3,30,15), (4,40,20), (5,50,25)))
    

    【讨论】:

      【解决方案2】:

      您可以使用正则表达式提取所需的数据

      val x = "Mon-18-June-2018,1:10:5,2:20:10,3:30:15,4:40:20,5:50:25"
      val regex = "[0-9]+:[0-9]+:[0-9]+".r
      println(Map(x.takeWhile(!_.equals(',')) -> regex
          .findAllIn(x)
          .toList
          .map(_.split(":").toVector).map{
              case Vector(a,b,c) => (a,b,c)
          }
      ))
      

      输出:

      Map(Mon-18-June-2018 -> List((1,10,5), (2,20,10), (3,30,15), (4,40,20), (5,50,25)))
      

      【讨论】:

        【解决方案3】:

        这里有一个使用正则表达式/模式匹配的解决方案:

        从您创建的列表开始:

        val allLists: List[List[String]] = List(List("Mon-18-June-2018", "1:10:5", "2:20:10", "3:30:15", "4:40:20", "5:50:25"),
            List("Mon-19-June-2018", "22:10:5", "2:220:10", "3:33:15", "4:40:20", "5:50:25"))
        

        我们为数字创建一个正则表达式:

        val numberRegex = """(\d+):(\d+):(\d+)""".r.unanchored
        

        现在我们映射列表:

        val result: Map[String, List[(Int, Int, Int)]] = allLists.map {
            case date :: (numbers:Seq[String]) => date -> // the first entry is the date
              numbers.map { // map the rest (numbers list)
                case numberRegex(x, y, z) => (x.toInt, y.toInt, z.toInt) 
              }
          }.toMap
        

        这将打印:

        Map(Mon-18-June-2018 -> List((1,10,5), (2,20,10), (3,30,15), (4,40,20), (5,50,25)), Mon-19-June-2018 -> List((22,10,5), (2,220,10), (3,33,15), (4,40,20), (5,50,25)))
        

        【讨论】:

          猜你喜欢
          • 2020-07-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-11-13
          • 2020-04-05
          • 2021-10-31
          • 1970-01-01
          相关资源
          最近更新 更多