如何基于具有任意元素的多个列表进行映射?
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 函数转换哈希图中的各个列表并按键查找,而不是为每个人的元素迭代所有这些列表可能会有所帮助?
我有以下型号:
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 函数转换哈希图中的各个列表并按键查找,而不是为每个人的元素迭代所有这些列表可能会有所帮助?