我有一个方法,我写的是通过执行api调用来增加人员数据并添加丰富的数据。
所以我有这个案例类:
case class Person(personData: PersonData, dataEnrichment: Option[DataEnrichment])
我的方法假设返回此案例类。
但之前我的过滤器很少,
如果人员身高不是"1.8 m"
,或者如果使用正则表达式在bio中找不到personId,我想返回Person
dataEnrichment = None
我的问题是人物身高和人物身份是选项本身。
所以它看起来像这样:
def enrichPersonObjWithApiCall(person: Person) = {
person.personData.height.map(_.equals("1.8 m")) match {
case Some(true) =>
val personId = person.personData.bio flatMap { comment =>
extractPersonIdIfExists(comment)
}
personId match {
case Some(perId) =>
apiCall(perId) map { apiRes =>
Person(
person.personData,
dataEnrichment = apiRes)
}
case _ =>
Future successful Person(
person.personData,
dataEnrichment = None)
}
case _ =>
Future successful Person(
person.personData,
dataEnrichment = None)
}
}
def extractPersonIdIfExists(personBio: String): Option[String] = {
val personIdRegex: Regex = """(?<=PersonId:)[^;]+""".r
personIdRegex.findFirstIn(personBio)
}
def apiCall(personId: String): Future[Option[DataEnrichment]] = {
???
}
case class DataEnrichment(res: Option[String])
case class PersonData(name: String, height: Option[String], bio: Option[String])
剂量似乎是scala最佳实践,就像那样执行它。你有更优雅的方法来获得相同的结果吗?
答案 0 :(得分:1)
使用[1-4]{0,5}
是处理for
值链的好方法:
Option
这相当于一系列def enrichPersonObjWithApiCall(person: Person): Future[Person] =
(
for {
height <- person.personData.height if height == "1.8 m"
comment <- person.personData.bio
perId <- extractPersonIdIfExists(comment)
} yield {
apiCall(perId).map(Person(person.personData, _))
}
).getOrElse(Future.successful(Person(person.personData, None)))
,map
和flatMap
来电,但更容易阅读。
答案 1 :(得分:0)
在这里,我试图让它更具惯用性和更短:
def enrichPersonObjWithApiCall(person: Person) = {
person.personData.height.collect {
case h if h == "1.8 m" =>
val personId = person.personData.bio.flatMap(extractPersonIdIfExists)
personId.map(
apiCall(_)
.map(apiRes => person.copy(dataEnrichment = apiRes))
)
}.flatten.getOrElse(
Future.successful(person.copy(dataEnrichment = None))
)
}
基本上,我们的想法是在适当的时候使用map
,flatMap
,collect
的适当的一元链而不是模式匹配。
答案 2 :(得分:0)
与Aivean的回答相同。我会使用map
flatMap
和filter
。
def enrichPersonObjWithApiCall(person: Person) = {
person.personData.height
.filter(_ == "1.8 m")
.flatMap{_=>
val personId = person.personData.bio
.flatMap(extractPersonIdIfExists)
personId.map(
apiCall(_)
.map(apiRes => person.copy(dataEnrichment = apiRes))
)
}.getOrElse(Future.successful(person))
}
对我来说,它更具可读性。