Scala for循环

时间:2020-01-09 10:47:19  来源:igfitidea点击:

只要特定条件为真,Scala for循环还将执行特定代码块。但是,它的工作原理与while循环有所不同。这是一个例子:

for(i <- 1 to 10) {
    println("i is " + i);
}

这个for循环迭代10次,对于每次迭代,都将范围内的下一个数字赋给val。

" i <"构造称为"生成器"。对于每次迭代,它都会使用值初始化vali。

" 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:",并添加元素的索引。

第三,使用生成器符号(&lt;)迭代数组。对于每次迭代,将数组中的下一个元素分配给" 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循环实际上更具可读性。