-1

I have a list of cars:

val cars = List(car1, car2, car3, car4, car5)
case class car(model: String, age: Int, partIds: Seq[String])

I now want to transform this list into a Map, where the key is the partId and the value is all the cars with that part.

val partMap: Map[String, List[Car]]
cool breeze
  • 4,461
  • 5
  • 38
  • 67

2 Answers2

2

You will need to jump through some hoops by using intermediate types. The solution is to first get from your List[Car] into to List[PartId -> Car]. Dropping the Seq of parts makes your life easer. You can group your cars easily.

The mapValues is a function on Map. It will iterate over every tuple and will require some function that takes a type equal to the value of your Map...in my case before mapValues I had a Map[String, List[String -> Car]].

The mapValues wants a function with the signature (carMapping : List[(String, Car]) : A ... our desired type is of course List[Car]

here is a something on groupBy and a little about mapValues: http://markusjais.com/the-groupby-method-from-scalas-collection-library/

  case class Car(model: String, age: Int, partIds: Seq[String])

  object ListToMap extends App {

    val car1 = Car("corolla", 1,  Seq("b"))
    val car2 = Car("camry",   5,  Seq("b", "c"))
    val car3 = Car("fit",     6,  Seq("e"))
    val car4 = Car("prelude", 2,  Seq("e", "f"))
    val car5 = Car("cobalt",  10, Seq("j"))

    val cars = List(car1, car2, car3, car4, car5)

    //For Every Car lets make the list of Tuples for PartId -> Car
    def partMapping(car : Car) : Seq[(String, Car)] = car.partIds.map(part => part -> car)


    def toPartMap(cars : List[Car]) : Map[String, List[Car]] =
      cars
        //Get the List of Tuples PartId -> Car and then flatten the internal list (same as map().flatten)
        .flatMap(partMapping)
        // group all the tuples by the partId
        .groupBy(_._1)
        // We currently have a Map[String, List[(partId -> Car)]] we need to clean that up a bit to remove the partId
        .mapValues( carMapping => carMapping.map(_._2))


    toPartMap(cars).foreach(println)
  }
Jono
  • 103
  • 5
  • I found out that mapValues only creates a view over the map. You may want to be carful using it: http://stackoverflow.com/questions/14882642/scala-why-mapvalues-produces-a-view-and-is-there-any-stable-alternatives – Jono Aug 11 '16 at 02:48
1
cars flatMap ( x => x.partIds map ((_, x))) groupBy (_._1) mapValues (_ map (_._2))
ryan
  • 974
  • 2
  • 7
  • 13
  • Can you explain what mapValues is doing? Not sure what the _._2 represents. – cool breeze Aug 10 '16 at 18:58
  • `cars flatMap ( x => x.partIds map ((_, x))) ` creates a List of tuples with partId as the first element and car as the second element. Then `groupBy` partId that creates a map partId -> (partId, car). `mapValues` maps the values `(partId, car)` to just `car` in this case. `_._2` meaning getting the 2nd item in the tuple. Hope this helps. – ryan Aug 10 '16 at 19:19