0Pricing
Scala for Backend Engineering & Functional Programming · 课时

使用 if 筛选

推导式中的守卫

使用 if 筛选 是 CoddyKit 上的免费 Scala for Backend Engineering & Functional Programming 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Scala for Backend Engineering & Functional Programming 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Scala for Backend Engineering & Functional Programming 课程共包含 4 节课。

for 推导式中的守卫

您可以在 for 推导式中添加一个称为守卫的 if 条件。它只保留满足条件的元素,就像 filter 一样。

object Main {
  def main(args: Array[String]): Unit = {
    val evens = for (x <- 1 to 10 if x % 2 == 0) yield x
    println(evens)
  }
}

守卫会展开为 withFilter

守卫 if cond 会被改写为对 withFilter 的调用(这是 filter 的惰性变体)。

  • for (x <- xs if p(x)) yield x
  • 会变成 xs.withFilter(p).map(x => x)
object Main {
  def main(args: Array[String]): Unit = {
    val sugar = for (x <- List(1, 2, 3, 4) if x > 2) yield x
    val desugared = List(1, 2, 3, 4).withFilter(_ > 2).map(x => x)
    println(sugar == desugared)
  }
}

为什么使用 withFilter 而不是 filter

withFilter 是惰性的:它不会创建中间集合。条件只有在后续的 map 或 flatMap 运行时才会应用,从而节省内存和计算量。

object Main {
  def main(args: Array[String]): Unit = {
    val nums = List(1, 2, 3, 4, 5, 6)
    val result = for (n <- nums if n % 3 == 0) yield n * 100
    println(result)
  }
}

多个守卫

您可以串联多个守卫。它们的组合方式类似逻辑 AND:元素必须满足所有条件才能保留下来。

object Main {
  def main(args: Array[String]): Unit = {
    val result = for {
      x <- 1 to 20
      if x % 2 == 0
      if x % 3 == 0
    } yield x
    println(result)
  }
}

带多个生成器的守卫

守卫可以出现在任意生成器之后,用于过滤该层迭代的值。请将守卫紧跟在它所检查的值所属的生成器之后。

object Main {
  def main(args: Array[String]): Unit = {
    val coprimeSums = for {
      x <- 1 to 3
      y <- 1 to 3
      if x != y
    } yield (x, y)
    println(coprimeSums)
  }
}

组合守卫和值绑定

您可以自由地将守卫(if)与值绑定(=)混合使用。顺序很重要:在守卫之前定义的绑定可以在该守卫中使用。

object Main {
  def main(args: Array[String]): Unit = {
    val result = for {
      x <- 1 to 6
      square = x * x
      if square > 10
    } yield square
    println(result)
  }
}

对 String 集合使用守卫

守卫适用于任何谓词,而不只是数值谓词。这里我们根据单词长度进行过滤。

object Main {
  def main(args: Array[String]): Unit = {
    val words = List("scala", "go", "java", "rust", "c")
    val longWords = for (w <- words if w.length >= 4) yield w.toUpperCase
    println(longWords)
  }
}

过滤 Options

对于 Option,不满足条件的守卫会将结果变为 None。这使得 for 推导式成为验证可选值的简洁方式。

object Main {
  def main(args: Array[String]): Unit = {
    val ok  = for (x <- Some(8) if x > 5) yield x
    val bad = for (x <- Some(3) if x > 5) yield x
    println(ok)
    println(bad)
  }
}

守卫的位置会改变含义

守卫只能看到在它上方绑定的值。将守卫放在它所需的生成器之前将无法编译。请始终将守卫放在相关生成器之后。

object Main {
  def main(args: Array[String]): Unit = {
    val result = for {
      x <- 1 to 3
      y <- 1 to 3
      if x + y == 4
    } yield s"$x + $y = ${x + y}"
    result.foreach(println)
  }
}

守卫与最终过滤

您可以在推导式之后过滤结果,但守卫会在迭代过程中进行过滤。当有多个生成器时,守卫可以及早剪枝,减少总的工作量。

object Main {
  def main(args: Array[String]): Unit = {
    val withGuard = for {
      x <- 1 to 100
      if x % 25 == 0
    } yield x
    println(withGuard)
  }
}

易读的验证流程

将多个守卫叠加起来,就像一份条件检查清单。这是实际 Scala 代码中使用 for 推导式最符合惯用风格的方式之一。

object Main {
  def main(args: Array[String]): Unit = {
    val valid = for {
      n <- List(4, 7, 12, 15, 20)
      if n > 5
      if n < 18
      if n % 2 == 0
    } yield n
    println(valid)
  }
}

快速检查

for 推导式中的守卫(if)会被脱糖为哪个方法?

回顾

您学习了 for 推导式中的守卫:

  • if cond 会在迭代过程中过滤元素
  • 守卫会脱糖为 withFilter(惰性过滤)
  • 多个守卫的组合方式类似逻辑 AND
  • 守卫只能看到在它上方绑定的值
  • 守卫可以与生成器和 = 绑定自由组合

常见问题解答

「使用 if 筛选」课时是免费的吗?

是的 — 「使用 if 筛选」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Scala for Backend Engineering & Functional Programming 课程的其余内容,请升级到 CoddyKit PRO。 Scala for Backend Engineering & Functional Programming 课程共包含 4 节课。

「使用 if 筛选」这节课中我会学到什么?

推导式中的守卫 你通过在浏览器中直接运行的动手代码来练习 Scala for Backend Engineering & Functional Programming,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Scala for Backend Engineering & Functional Programming 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Scala for Backend Engineering & Functional Programming 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「使用 if 筛选」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Scala for Backend Engineering & Functional Programming 课中编写并运行代码吗?

能。每节 Scala for Backend Engineering & Functional Programming 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 展开 for
  2. 使用 if 筛选
  3. 多个生成器
  4. 与 Option 和 Future 一起使用
← 返回 Scala for Backend Engineering & Functional Programming