如何基于具有任意元素的多个列表进行映射?

How to map based on multiple lists with arbitrary elements?

我有以下型号:

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)

我想根据以下列表构建 List[Info]

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

应根据personL收集信息,例如:

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

结果:

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

现在我想知道是否有比我的 map 构造更简洁的表达式正好解决了我的问题。

这是一个选项,首先构建从 ownerid 到模型和地址的映射,然后在遍历人员列表的同时查找信息:

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

我会说用于理解。如果您恰好需要在那种情况下类似于 left join 的结果,那么 for 理解仍然很难看:

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)

请注意,在这种特殊情况下,您可以删除 .toList 调用,因为两个选项生成器出现在集合生成器之后。

如果您可以牺牲默认模型/地址值,那么它看起来很简单:

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)

希望对您有所帮助。

可能会使用 map 函数转换哈希图中的各个列表并按键查找,而不是为每个人的元素迭代所有这些列表可能会有所帮助?