Как разделить список для добавления на карту в Scala с разными типами данных - PullRequest
0 голосов
/ 13 апреля 2020

У меня есть некоторые необработанные тестовые данные, которые мне нужно разделить на карту формата:

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

Мне удалось прочитать данные в виде списка и привести пример одной строки данных ниже:

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

Выше представлено следующее: Маршрут, номер этапа: имя этапа: общее расстояние этапа

Таким образом, каждый набор из 3 значений (т. Е. 1: Городские камеры: 5) должен быть добавлен в раздел карты [Int, String, Float] с ключом.

Это мой код для чтения файла и добавления его в список:

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

Я хотел бы написать функцию для разделения данных и добавления их на карту, по сути, делая это:

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)

Как добавить данные на карту в желаемом формате?

Ответы [ 2 ]

1 голос
/ 13 апреля 2020

Мое предложение будет использовать foldLeft. Примерно так:

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

Начните с пустой карты и добавьте ключ-> значения для каждой строки. Кроме того, попробуйте выражения соответствия, когда вы анализируете данные в списке (это делает часть listOfValues).

0 голосов
/ 13 апреля 2020

Этот подход заключается в сопоставлении скороговорки и рекурсии хвоста. Я думаю, что это работает очень хорошо. Сначала я конвертирую файл в List [Array [String]]. Во-вторых, я рекурсивно вызываю l oop в go через список и строю карту. В-третьих, внутри функции l oop, которую я вызываю make List, для рекурсивного построения списка кортежей.

Например:

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

и ожидаемый результат

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

Надеюсь, это может быть полезно.

С уважением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...