2017-06-17 2 views
1

Ich habe folgendes Modell:Wie wird basierend auf mehreren Listen mit beliebigen Elementen gemappt?

case class Car(brand: String, year: Int, model: String, ownerId: String) 
case class Person(firstName: String, lastName: String, id: String) 
case class House(address: String, size: Int, ownerId: String) 
case class Info(id: String, lastName: String, carModel: String, address: String) 

ich auf den folgenden Listen ein List[Info] Basis aufbauen wollen:

val personL: List[Person] = List(Person("John", "Doe", "1"), Person("Jane", "Doe", "2")) 
val carL: List[Car] = List(Car("Mercedes", 1999, "G", "1"), Car("Tesla", 2016, "S", "4"), Car("VW", 2015, "Golf", "2")) 
val houseL: List[House] = List(House("Str. 1", 1000, "2"), House("Bvl. 3", 150, "8")) 

Die Informationen gesammelt auf der Grundlage der personL, zum Beispiel werden sollten:

val info = personL.map { p => 
     val car = carL.find(_.ownerId.equals(p.id)) 
     val house = houseL.find(_.ownerId.equals(p.id)) 
     val carModel = car.map(_.model) 
     val address = house.map(_.address) 
     Info(p.id, p.lastName, carModel.getOrElse(""), address.getOrElse("")) 
     } 

Ergebnis:

info: List[Info] = List(Info(1,Doe,G,), Info(2,Doe,Golf,Str. 1)) 

Jetzt frage ich mich, ob es einen Ausdruck gibt, der prägnanter als mein Kartenkonstrukt ist, das genau mein Problem löst.

Antwort

2

ist hier eine Option durch den Aufbau der Karten von ownerid zunächst zu modellieren und adressieren, und dann die Info nachschauen, während sie durch die Person Liste Looping:

val carMap = carL.map(car => car.ownerId -> car.model).toMap 
// carMap: scala.collection.immutable.Map[String,String] = Map(1 -> G, 4 -> S, 2 -> Golf) 

val addrMap = houseL.map(house => house.ownerId -> house.address).toMap 
// addrMap: scala.collection.immutable.Map[String,String] = Map(2 -> Str. 1, 8 -> Bvl. 3) 

personL.map(p => Info(p.id, p.lastName, carMap.getOrElse(p.id, ""), addrMap.getOrElse(p.id, ""))) 
// res3: List[Info] = List(Info(1,Doe,G,), Info(2,Doe,Golf,Str. 1)) 
0

ich für Comprehensions sagen würde. Wenn Sie genau das Ergebnis müssen die in diesem Fall würde ähneln einem left join dann die für das Verständnis noch hässlich ist:

for { 
    person <- persons 
    model <- cars.find(_.ownerId == person.id).map(_.model).orElse(Some("")).toList 
    address <- houses.find(_.ownerId == person.id).map(_.address).orElse(Some("")).toList 
} yield Info(person.id, person.lastName, model, address) 

Beachten Sie, dass die .toList Anruf in diesem Ausnahmefall, da die beiden Option Generatoren erscheinen nach der Sammlung entfernen Generatoren.

Wenn Sie die Standardmodell/Adresswerte opfern kann dann sieht es einfach genug:

for { 
    person <- persons 
    car <- cars if car.ownerId == person.id 
    house <- houses if house.ownerId == person.id 
} yield Info(person.id, person.lastName, car.model, car.address) 

Hoffnung, das hilft.

0

Konvertieren Sie die einzelnen Listen in Hashmaps möglicherweise mit einer Kartenfunktion, und suchen Sie nach Schlüsseln, anstatt alle diese Listen für jedes Element der Person zu wiederholen?

Verwandte Themen