获取案例类中相同类型的字段值列表

问题描述 投票:1回答:2

我有一个这样的课程,如果有人感兴趣,我会详细解答重叠算法的哪一部分出错了,我希望将来在数据中增加许多其他可能的无效性。

case class Validity(grouping: Boolean = true,
                    matchingValuesValidation: Boolean = true) {
  def compute: Boolean =
    List(grouping,
         matchingValuesValidation
    ).forall(identity)

  def merge(ot: Validity): Validity =
    Validity(
      grouping && ot.grouping,
      matchingValuesValidation && ot.matchingValuesValidation
    )
}

我知道所有字段都是布尔值,计算不会改变。我想让方法计算和合并以某种方式遍历所有字段,所以如果我增强它,就不需要做3次。如果我使用Map,我可以添加我想要的任何键 - >值对,这是不可取的,我想保留结构。同时,我想通过简单地向该类添加另一个布尔参数来增强该类。非常感谢任何想法,提前感谢

scala
2个回答
1
投票

你知道吗? YOLO。

case class Validity(grouping: Boolean = true, matchingValuesValidation: Boolean = true) {

  def values: List[Boolean] = {
    import scala.reflect.runtime.universe._
    val fields = typeOf[Validity].members.collect { case m: MethodSymbol if m.isCaseAccessor => m }.toList
    val mirror = runtimeMirror(this.getClass.getClassLoader)
    fields.map(mirror.reflect(this).reflectField(_).get.asInstanceOf[Boolean])
  }

  def compute: Boolean = values.forall(identity)
  def merge(ot: Validity) = Validity.fromValues(this.values.zip(ot.values).map(v => v._1 && v._2).reverse)
}

object Validity {
  def fromValues(values: List[Boolean]): Validity = {
    import scala.reflect.runtime.universe._
    val mirror = runtimeMirror(Validity.getClass.getClassLoader)
    val constructorSymbol = typeOf[Validity].decl(termNames.CONSTRUCTOR).asMethod
    val classSymbol = mirror.reflectClass(typeOf[Validity].typeSymbol.asClass)
    val constructor = classSymbol.reflectConstructor(constructorSymbol)
    constructor(values:_*).asInstanceOf[Validity]
  }
}

1
投票

而不是反射你可以使用无形来为你做繁重的工作:

import shapeless.ops.hlist.{Mapper, Zip}
import shapeless.{::, Generic, HList, HNil, Poly1}

private sealed trait lowPrioMergerMapper extends Poly1 {
  implicit def mapperT[T]: Case.Aux[(T, T), T] = at[(T, T)] { case (v1, _) => v1}
}
private object MergerMapper extends lowPrioMergerMapper {

  implicit def mapperBoolean: Case.Aux[(Boolean, Boolean), Boolean] = at[(Boolean, Boolean)] { case (v1, v2) => v1 && v2 }
}

def booleanFieldMerger[T, HL <: HList, ZOut <: HList](a: T, b: T)(
  implicit
  gen: Generic.Aux[T, HL],
  zipWith: Zip.Aux[HL :: HL :: HNil, ZOut],
  mapper: Mapper.Aux[MergerMapper.type ,ZOut, HL]
): T = {
  val aRepr = gen.to(a)
  val bRepr = gen.to(b)
  gen.from((aRepr zip bRepr) map MergerMapper)
}

用法如下:

val validity = Validity()
val validity2 = Validity(a = false)
val validity3 = Validity(b = false)
val validity4 = Validity(a = false, b = false)

booleanFieldMerger(validity,validity2) shouldBe validity2
booleanFieldMerger(validity2,validity3) shouldBe validity4
List(validity2,validity3).fold(validity)((a,b) => booleanFieldMerger(a,b)) shouldBe validity4

并且为了评估您可以使用的字段:

import shapeless.HList
import shapeless.ops.hlist._

def evaluateBooleanFields[T, HL <: HList](input: T)(
  implicit
  gen: Generic.Aux[T, HL],
  toTrav: ToList[HL,Any]): Boolean = {
  gen.to(input).toList.foldLeft(true){
    case (acc, e: Boolean) => acc && e
    case (acc, _) => acc}
}

用法与上面相同:

evaluateBooleanFields(validity) shouldBe true
evaluateBooleanFields(validity2) shouldBe false
© www.soinside.com 2019 - 2024. All rights reserved.