You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于文本表达式过滤Scala数据?求可用类库及方案

Scala 动态筛选条件解决方案

针对你需要解析文本中的条件字符串并应用到Example实例的需求,以下是几个实用的实现方案:

1. 使用 Scala-Expr 库

Scala-Expr 支持直接解析字符串表达式并在 Scala 对象上求值,完美匹配你的条件格式需求。

步骤

  • 添加 SBT 依赖:
libraryDependencies += "com.github.julien-truffaut" %% "scala-expr" % "0.1.0"
  • 解析条件并验证数据:
import scalaexpr.Expr

// 从数据库获取的 Example 列表
val examples: List[Example] = List(Example(4.0, 60.0), Example(3.0, 70.0))
// 读取文本文件中的所有条件行
val conditions = scala.io.Source.fromFile("conditions.txt").getLines().toList

// 逐个检查条件是否有匹配数据
conditions.foreach { conditionStr =>
  val filterExpr = Expr[Example => Boolean](conditionStr)
  val hasMatch = examples.exists(filterExpr.eval)
  println(s"条件 '$conditionStr' 是否存在匹配数据: $hasMatch")
}

该库支持>、<、==等比较运算符,以及and、or、not逻辑运算符,无需额外适配即可处理你的条件格式。

2. 基于 FastParse 自定义解析器

如果不想引入第三方库,可以用 FastParse 手写轻量表达式解析器,灵活性更高。

步骤

  • 添加 SBT 依赖:
libraryDependencies += "com.lihaoyi" %% "fastparse" % "2.3.3"
  • 实现解析逻辑:
import fastparse._, NoWhitespace._

case class Example(a: Double, b: Double)

object ConditionParser {
  // 解析数值
  private def number[_: P]: P[Double] = P(CharIn("0-9").rep(1) ~ "." ~ CharIn("0-9").rep(1)).!.map(_.toDouble)
  // 解析字段名
  private def field[_: P]: P[String] = P(CharIn("a-z").rep(1)).!
  // 解析比较运算符
  private def op[_: P]: P[(Double, Double) => Boolean] = P(
    ">" ~ Pass.map((x: Double, y: Double) => x > y) |
    "<" ~ Pass.map((x: Double, y: Double) => x < y) |
    "==" ~ Pass.map((x: Double, y: Double) => x == y)
  )
  // 解析单个条件
  private def singleCondition[_: P]: P[Example => Boolean] = P(
    field ~ op ~ number
  ).map { case (field, op, num) =>
    example => op(field match {
      case "a" => example.a
      case "b" => example.b
    }, num)
  }
  // 解析逻辑组合(and/or)
  private def condition[_: P]: P[Example => Boolean] = P(
    singleCondition ~ ((" and " | " or ") ~ singleCondition).rep
  ).map { case (first, rest) =>
    rest.foldLeft(first) {
      case (acc, (" and ", cond)) => example => acc(example) && cond(example)
      case (acc, (" or ", cond)) => example => acc(example) || cond(example)
    }
  }

  def parse(str: String): Example => Boolean = parse(str, condition(_)).get.value
}

// 使用示例
val examples = List(Example(4.0, 60.0), Example(3.0, 70.0))
val filterFn = ConditionParser.parse("a > 3.7 and b < 67.2")
val hasMatch = examples.exists(filterFn)
println(s"是否存在匹配数据: $hasMatch")

这种方式可以完全自定义支持的运算符和字段,适合你的简单业务场景,没有冗余依赖。

3. 反射动态编译(仅用于测试)

利用 Scala 反射动态编译条件字符串为函数,但存在代码注入风险,不推荐生产环境使用。

import scala.reflect.runtime.universe._
import scala.tools.reflect.ToolBox

val tb = runtimeMirror(getClass.getClassLoader).mkToolBox()

val example = Example(4.0, 60.0)
val conditionStr = "a > 3.7 and b < 67.2"
// 拼接成可编译的代码字符串
val code = s"""(example: Example) => example.$conditionStr"""
val filterFn = tb.compile(tb.parse(code)).asInstanceOf[Example => Boolean]
println(filterFn(example)) // 输出 true

需要额外添加scala-compiler依赖,仅适合快速验证场景。

内容的提问来源于stack exchange,提问作者ruoyu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 20:22:19