Scala for循环
只要特定条件为真,Scala for循环还将执行特定代码块。但是,它的工作原理与while循环有所不同。这是一个例子:
for(i <- 1 to 10) { println("i is " + i); }
这个for循环迭代10次,对于每次迭代,都将范围内的下一个数字赋给val。
" i <"构造称为"生成器"。对于每次迭代,它都会使用值初始化val
i。
" 1到10"称为"范围"类型。它返回一个包含从1到10的值的范围,包括两个数字。范围类型在其他文本中有更详细的描述。
" 1到10"实际上是一个返回" Range"类型的方法调用。相当于
(1).to(10);
Scala对域特定语言(DSL)的支持中的文本中更详细地描述了它的工作方式。
在for循环中省略{}
如果循环的主体由一个语句组成,则可以在for循环中省略{}。这是一个例子:
for(i <- 1 to 10) println("i is " + i);
to 和until比较
创建" Range"对象时,可以使用关键字" to"或者" until"。区别在于," to"包括该范围内的最后一个值,而" until"将其排除在外。这是两个示例:
for(i <- 1 to 10) { println("i is " + i); } for(i <- 1 until 10) { println("i is " + i); }
第一个循环迭代10次,从1循环到10,包括10.
第二个循环从1到9进行9次迭代,不包括上边界值10.
迭代集合和数组
我们可以使用for循环迭代集合或者数组,如下所示:
var myArray : Array[String] = new Array[String](10); for(i <- 0 until myArray.length){ myArray(i) = "value is: " + i; } for(value : String <- myArray ) { println(value); }
首先创建一个数组。
其次,将数组中的每个元素初始化为文本" value is:",并添加元素的索引。
第三,使用生成器符号(<
)迭代数组。对于每次迭代,将数组中的下一个元素分配给" val"值,然后将其打印到控制台。
过滤循环
在Scala for循环中,可以将过滤应用于集合或者数组的迭代。方法如下:
var myArray : Array[String] = new Array[String](10); for(i <- 0 until myArray.length){ myArray(i) = "value is: " + i; } for(value : String <- myArray if value.endsWith("5")) { println(value); }
注意以粗体标记的if value.endsWith(" 5")
。此条件或者过滤器意味着,仅当分配了"值"的字符串以文本" 5"结尾时,for循环才会执行其主体。只有一个数组元素以文本" 5"结尾,因此for循环主体仅执行一次。
上面的for循环过滤等效于以下代码:
for(value : String <- myArray) { if value.endsWith("5"){ println(value); } }
就个人而言,我实际上更喜欢使用旧的好方法(第二种方法)。尽管新方法更短一些,但阅读起来并不容易。尤其是当条件更加复杂时,我们将在后面看到。
多个for环路滤波器
我们可以应用多个for循环过滤器,如下所示:
for(value : String <- myArray if value.endsWith("5"); if value.indexOf("value") != -1 ) { println(value); }
请注意for循环声明中的两个if语句。它们之间用分号分隔。这两个条件现在都必须为真,才能执行for循环主体。
上面的for循环等效于这个古老的for循环:
for(value : String <- myArray) { if( value.endsWith("5") && value.indexOf("value") != -1){ println(value); } }
就个人而言,我仍然认为第二个较旧的版本更易于阅读和理解。
嵌套迭代
可以在单个for循环中执行嵌套循环。假设我们有一个数组数组。然后,我们可以像这样迭代它们:
var myArray : Array[Array[String]] = new Array[Array[String]](10); for(i <- 0 until myArray.length){ myArray(i) = new Array[String](10); for(j <- 0 until myArray(i).length){ myArray(i)(j) = "value is: " + i + ", " + j; } } for(anArray : Array[String] <- myArray; aString : String <- anArray ) { println(aString); }
首先,创建一个数组数组,并使用数组和字符串值对其进行初始化。
其次,使用嵌套循环来迭代数组的数组。首先,在数组数组中的每个String数组都被分配给val``anArray
。然后,每个String数组的每个String值都分配给valu` aString。
上面的嵌套循环等效于嵌套循环的老派:
for(anArray : Array[String] <- myArray) { for(aString : String <- anArray) { println(aString); } }
同样,我仍然更喜欢循环式的老派。
中游变量绑定
可以在嵌套迭代的中间将值绑定到变量,如下所示:
for(anArray : Array[String] <- myArray; aString : String <- anArray; aStringUC = aString.toUpperCase() if aStringUC.indexOf("VALUE") != -1; if aStringUC.indexOf("5") != -1 ) { println(aString); }
两个过滤条件需要aString.toUpperCase()
结果。通过将它们嵌套在每个if语句中,而不是两次计算.toUpperCase()值,而是仅计算一次aString大写版本并将其分配给变量aStringUC。现在,两个过滤条件(if语句)可以引用此"中间流"计算值。
使用这个古老的for循环可以达到相同的效果:
for(anArray : Array[String] <- myArray) { for(aString : String <- anArray) { var aStringUC = aString.toUpperCase(); if(aStringUC.indexOf("5") != -1 && aStringUC.indexOf("VALUE") != -1){ println(aString); } } }
再一次,我相信这个古老的for循环实际上更具可读性。