Scala:for 循环遍历形式基本简单介绍(基础,高级,for-yield,特殊场景)

发布于:2025-03-04 ⋅ 阅读:(16) ⋅ 点赞:(0)

一、基础遍历形式

1. 遍历范围(Range)
  • 语法:使用 to(闭区间)或 until(左闭右开区间)。
  • 示例

    scala复制代码

    // 遍历 1 到 3(包含 3)
    for (i <- 1 to 3) {
      println(i) // 输出 1, 2, 3
    }
    
    // 遍历 1 到 2(不包含 3)
    for (i <- 1 until 3) {
      println(i) // 输出 1, 2
    }
2. 遍历集合(List/Array/Set等)
  • 语法:直接遍历集合中的每个元素。
  • 示例

    scala复制代码

    val fruits = List("Apple", "Banana", "Orange")
    
    for (fruit <- fruits) {
      println(fruit) // 依次输出每个水果名
    }

二、高级遍历形式

1. 多生成器(嵌套循环)
  • 语法:多个 <- 生成器,实现嵌套循环(笛卡尔积)。
  • 示例

    scala复制代码

    val colors = List("Red", "Blue")
    val sizes = List("S", "L")
    
    for {
      color <- colors
      size  <- sizes
    } {
      println(s"$color-$size") // 输出 Red-S, Red-L, Blue-S, Blue-L
    }
2. 条件过滤(Guard 守卫)
  • 语法:用 if 在生成器后添加过滤条件。
  • 示例

    scala复制代码

    val nums = List(1, 2, 3, 4, 5)
    
    for {
      n <- nums
      if n % 2 == 0  // 只保留偶数
      if n > 2       // 多重条件(等效于 &&)
    } {
      println(n) // 输出 4
    }
3. 模式匹配解构
  • 语法:在生成器中直接解构元组、Case Class 等。
  • 示例

    scala复制代码

    val pairs = List((1, "A"), (2, "B"), (3, "C"))
    
    // 解构元组
    for ((num, char) <- pairs) {
      println(s"$num-$char") // 输出 1-A, 2-B, 3-C
    }

三、生成新集合(for-yield

1. 基础用法
  • 语法for 后必须加 yield,生成新集合。
  • 示例

    scala复制代码

    val nums = List(1, 2, 3)
    val doubled = for (n <- nums) yield n * 2  // List(2, 4, 6)
2. 复杂转换
  • 示例:结合多生成器、过滤和模式匹配。

    scala复制代码

    val pairs = List(("A", 1), ("B", 2), ("C", 3))
    
    val result = for {
      (char, num) <- pairs  // 解构元组
      if num > 1            // 过滤条件
      suffix <- List("X", "Y")  // 嵌套生成器
    } yield s"$char$num$suffix"
    
    // 结果:List("B2X", "B2Y", "C3X", "C3Y")

四、特殊场景

1. 遍历 Option 类型
  • 用途:优雅处理可能为 None 的值。
  • 示例

    scala复制代码

    val a: Option[Int] = Some(2)
    val b: Option[Int] = Some(3)
    
    val sum = for {
      x <- a  // 若 a 是 None,直接返回 None
      y <- b
    } yield x + y  // Some(5)
2. 遍历 Map
  • 语法:遍历键值对(每个元素是 (K, V) 元组)。
  • 示例

    scala复制代码

    val map = Map("A" -> 1, "B" -> 2)
    
    for ((k, v) <- map) {
      println(s"Key: $k, Value: $v")
    }

五、底层原理

Scala 的 for 循环会被编译器转换为 mapflatMap 和 filter 的组合:

  • 单生成器 + yield

    scala复制代码

    for (x <- list) yield f(x)
    // 等价于
    list.map(x => f(x))
  • 多生成器 + 过滤

    scala复制代码

    for {
      x <- list1
      y <- list2
      if cond
    } yield f(x, y)
    // 等价于
    list1.flatMap(x => list2.filter(y => cond).map(y => f(x, y)))

六、常见错误

  1. 忘记 yield

    scala复制代码

    // 错误:返回 Unit,不会生成新集合
    val result = for (n <- List(1,2)) { n * 2 }
    // 正确:加 yield
    val result = for (n <- List(1,2)) yield n * 2
  2. 守卫位置错误

    scala复制代码

    // 错误:if 必须跟在生成器后
    for (n <- List(1,2); if n > 1; m <- List(3,4)) yield m

总结

  • 基础:范围遍历、集合遍历。
  • 进阶:多生成器、过滤、模式匹配。
  • 生成集合:必须用 yield,类型与输入一致。
  • 底层:转换为 map/flatMap/filter,理解性能影响。