Scala for for循环中的过滤

时间:2014-02-03 05:33:07

标签: scala

我是Scala的新手,我现在正在学习for语句。我读了这篇教程http://joelabrahamsson.com/learning-scala-part-six-if-statements-and-loops/

在本教程中,有一个例子,

for (person: Person <- people
    if !person.female;
    name = person.name;
    if name.contains("Ewing"))
  println(name)

如果将这个for循环与Java中的for循环进行比较,就像

一样
for(person: people) {
   if (!person.female) {
     String name = person.name;
     if (name.contains("Ewing"))   
       println(name)
   }
}

或者像这样:

for(person: people) {
   String name = person.name;
   if (!person.female && name.contains("Ewing")) {
     println(name)
   }
}

如果第一个过滤条件&#34; if!person.female;&#34;是否执行了操作(在此示例中为name = person.name;)不满意?

谢谢!

4 个答案:

答案 0 :(得分:1)

Scala for理解展现为mapflatmapfilter的组合。在您的情况下,if实际上是对“循环”的“迭代”中出现的所有值的过滤器。因此,如果不满足if条件,则循环将跳过此迭代,因此您的Java for循环的行为与Scala示例相同。

例如,在REPL中尝试:

scala> val l = List(1, 2, 3, 4, 5, 6)
l: List[Int] = List(1, 2, 3, 4, 5, 6)

scala> for (i <- l
     |      if(i%2 == 0))
     |      println(i)
2
4
6

scala> 

这相当于:

l.filter(_%2 == 0).foreach(println)

答案 1 :(得分:1)

尝试一下!

for{
  x <- 1 to 10
  if x % 3 == 0
  y = println(f"x=$x")
  if x % 2 == 0
} {
  println(x)
}

打印:

x=3
x=6
x=9
6

这意味着y=行在第二个if过滤器之前发生。

答案 2 :(得分:1)

要查看scala编译器生成的内容,请编译为scalac -Xprint:typer。它给出了:

  people.withFilter(((check$ifrefutable$1: typer.Person) => check$ifrefutable$1: @scala.unchecked match {
  case (person @ (_: Person)) => true
  case _ => false
}))
//filter is acting as your if-clause
.withFilter(((person: Person) => person.<female: error>.unary_!)).map(((person: Person) => {
  val name = person.name;
  scala.Tuple2(person, name)
}))
//Your next if-clause
.withFilter(((x$1) => x$1: @scala.unchecked match {
  case scala.Tuple2((person @ (_: Person)), (name @ _)) => name.contains("Ewing")
}))
//Print each of them
.foreach(((x$2) => x$2: @scala.unchecked match {
        case scala.Tuple2((person @ (_: Person)), (name @ _)) => println(name)
      }))
    }
  }

简而言之,它就像你提到的第一个案例一样。但作为一个概念,我们始终建议将理解视为mapforeachflatmap等的映射。

这是因为在处理yield的许多情况下,您需要根据foreachfilter来管理类型和思维(在java意义上是foreach并且if)不会涵盖所有情况。例如,请考虑以下内容:

scala> for(x <- Option(1);
     | u <- scala.util.Left(2)
     | ) yield (x,u)
<console>:9: error: value map is not a member of scala.util.Left[Int,Nothing]
              u <- scala.util.Left(2)

以上for理解使用flatmapmap。考虑Java for循环(foreach基本上`)将无助于找到原因。

答案 3 :(得分:0)

我认为它不会评估以下表达式,因为它是使用AND条件执行此操作的常见实现。你可以在这里看到
http://www.scala-lang.org/api/current/index.html#scala.Boolean
当使用&amp;&amp;

时,scala也有这种短路实现