【问题标题】:Scala: Dynamic selection criteria as a method argumentScala:作为方法参数的动态选择标准
【发布时间】:2015-01-06 05:14:51
【问题描述】:

我的目的是在 Scala 中创建一个函数,它接受某种动态查询(类似于模式匹配中的case 表达式)并在List 中返回匹配的实例。假设列表由case class Person 的实例组成,这些实例几乎没有不同类型的属性。该函数应该能够接受某些字段的值的动态组合,并返回匹配的Persons。我正在专门寻找一个干净的解决方案。使用此类函数的一种可能方法是将具有匿名类型的对象作为查询(“模式”)传递:

def find(?): List<Person> = { ? }

val matches = find(new { val name = "Name"; val gender = Gender.MALE })

理想情况下,我想开发一种简洁的方式来传递条件,而不是具体的值,但这不是必需的。因为我正在学习 Scala,所以我不知道实现这样一个东西的所有技术。在 C# 中,我使用匿名类型(类似于上面的第二行代码)和dynamic 参数来实现类似的东西。 Scala 中什么是干净优雅的解决方案?

【问题讨论】:

  • 匿名谓词不够清晰的解决办法? xs.find(person =&gt; person.name == "Name" &amp;&amp; person.gender == Gender.MALE)?
  • 如果条件是静态的,它们就是。在运行前,并不确定,例如是否应该检查名称。
  • 您所描述的内容类似于 ScalaTest 的匹配器,您可以在其中编写类似 person should have ('name ("Name"), 'gender (Gender.MALE)) 的内容。虽然匹配器用于断言,但您可以根据自己的目的调整实现。看看“使用 have 检查任意属性”:scalatest.org/user_guide/matchers_quick_reference

标签: scala pattern-matching anonymous-types


【解决方案1】:

我不确定这是否是您正在寻找的东西,但让我们尝试一下:

首先,我们将Person 定义为case class Person(name: String, gender: Gender.Value),其中Gender 是已定义的枚举。

然后我们创建一个 Query 案例类,它具有相同的字段,但作为默认为 None 的选项,以及将查询与人员进行比较的方法:

case class Query(name: Option[String] = None, 
                 gender: Option[Gender.Value] = None){

  def ===(person: Person) = check(person.name, name) && 
                            check(person.gender, gender)

  private def check[T](field: T, q: Option[T]) = field == q.getOrElse(field)
}

不幸的是,在此解决方案中,=== 必须为每个字段分别调用 check。让我们现在就这样吧。也许就足够了(因为,例如,字段列表不会改变)。

请注意,如果查询的选项是 Nonecheck 返回 true,因此您不必传递查询的所有字段:

val q = Query(name = Some("Ann")) // the gender is not important
q === Person("Ann", Gender.FEMALE) // returns true

最后是find 方法:

def find(people: List[Person], query: Query) = people.filter(query === _)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-24
    • 2022-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-28
    • 1970-01-01
    相关资源
    最近更新 更多