过滤scala中选项的定义字段

时间:2018-07-18 08:12:53

标签: scala

我有一个带有选项的案例类:

case class PersonUpdate(name: Option[String], age: Option[Int], country: Option[String])

,我需要检查定义了哪些值,并使用其名称和值生成一个映射,例如:

如果我有这个对象:

val perUpdate = PersonUpdate(Option("john"), None, Option("England"))

地图看起来应该像这样:

val result = Map("people.$.name" -> "john", "people.$.country" -> "England")

有效地执行Scala方法的最佳方法是什么?

2 个答案:

答案 0 :(得分:-1)

对于您的具体情况,您可以执行以下操作:

List(
  perUpdate.name.map("people.$.name" -> _),
  perUpdate.age.map("people.$.age" -> _.toString),
  perUpdate.country.map("people.$.country" -> _)
).flatten.toMap

您可以有一个更通用的解决方案,但这并不是特别有效:

perUpdate.getClass.getDeclaredFields.flatMap { f =>
  f.setAccessible(true)

  f.get(perUpdate).asInstanceOf[Option[Any]].map("people.$."+f.getName -> _.toString)
}.toMap

要仅提取某些字段,请尝试以下操作:

val fieldNames = List("name", "age", "country")

fieldNames.flatMap{ fieldName =>
  val fieldValue = perUpdate.getClass.getDeclaredField(fieldName)
  fieldValue.setAccessible(true)

  fieldValue.get(perUpdate).asInstanceOf[Option[Any]].map("people.$."+fieldName -> _.toString)
}.toMap

答案 1 :(得分:-1)

案例类是Product的实例,可让您遍历其成员而无需反思:

Seq("name", "age", "country")
  .map { "people.$." + _ }
  .iterator
  .zip(perUpdate.productIterator)
  .collect { case (k, Some(v)) => k -> v }
  .toMap