我的案例类别为Contact
和Person
:
case class Contact(id: String, name: String)
case class Person(id: String, name: String, age: Int, contacts: List[Contact])
让我说我有Person
的列表:
val pesonList = List(
Person(1, "john", 30, List(Contact(5,"mark"),Contact(6,"tamy"),Contact(7,"mary"))),
Person(2, "jeff", 40, List(Contact(8,"lary"),Contact(9,"gary"),Contact(10,"sam")))
)
我需要对此pesonList
进行展平并将其转换为以下列表:
case class FlattenPerson(personId: String, contactId: Option[String], personName: String)
所以结果将是:
val flattenPersonList = List(
FlattenPerson(1,"john"),
FlattenPerson(1,5,"mark"),
FlattenPerson(1,6,"tamy"),
FlattenPerson(1, 7"mary"),
FlattenPerson(2,"jeff"),
FlattenPerson(2,8,"lary"),
FlattenPerson(2,9,"gary"),
FlattenPerson(2,10,"sam")
)
我发现了一种看起来像在起作用的方法,但是剂量似乎是正确的方法……它可能会破裂,scala可能有一种更有效的方法。
这是我能想到的:
val people = pesonList.map(person => {
FlattenPerson(person.id, None, person.name)
})
val contacts = pesonList.flatMap(person => {
person.contacts.map(contact => {
FlattenPerson(person.id, Some(contact.id), contact.name)
})
})
val res = people ++ contacts
这也将导致性能下降,我需要为我的应用获得的每个api调用执行此操作,并且它可以分配调用,还需要过滤res。
希望在这里获得帮助
答案 0 :(得分:3)
我认为flatMap()
可以满足您的需求。
personList.flatMap{pson =>
FlattenPerson(pson.id, None, pson.name) ::
pson.contacts.map(cntc => FlattenPerson(pson.id, Some(cntc.id), cntc.name))
}
//res0: List[FlattenPerson] = List(FlattenPerson(1,None,john)
// , FlattenPerson(1,Some(5),mark)
// , FlattenPerson(1,Some(6),tamy)
// , FlattenPerson(1,Some(7),mary)
// , FlattenPerson(2,None,jeff)
// , FlattenPerson(2,Some(8),lary)
// , FlattenPerson(2,Some(9),gary)
// , FlattenPerson(2,Some(10),sam))
答案 1 :(得分:0)
这里供参考,是该算法的递归版本,其中包括单次过滤。这似乎比在结果上调用.filter(f)
更快。未过滤的递归版本没有实际的性能优势。
def flattenPeople(people: List[Person], f: FlattenPerson => Boolean): List[FlattenPerson] = {
@annotation.tailrec
def loop(person: Person, contacts: List[Contact], people: List[Person], res: List[FlattenPerson]): List[FlattenPerson] =
contacts match {
case Contact(id, name) :: tail =>
val newPerson = FlattenPerson(person.id, Some(id), name)
if (f(newPerson)) {
loop(person, tail, people, newPerson +: res)
} else {
loop(person, tail, people, res)
}
case _ =>
val newPerson = FlattenPerson(person.id, None, person.name)
val newRes = if (f(newPerson)) newPerson +: res else res
people match {
case p :: tail =>
loop(p, p.contacts, tail, newRes)
case Nil =>
newRes.reverse
}
}
people match {
case p :: tail => loop(p, p.contacts, tail, Nil)
case _ => Nil
}
}