如何在scala中的for循环外打印一个值?

时间:2018-04-12 17:11:33

标签: scala

我是scala的新手,想知道如何访问在for循环中定义的val,并希望将该val写入for循环外的文件。

def time[A](logFile: String, description: String)(job: => A): Unit = {
    var totalDuration: Long = 0

    for (i <- 1 to 3) {
        val currentTime = System.currentTimeMillis
        val result = job
        val finalTime = System.currentTimeMillis
        val duration = finalTime - currentTime

        totalDuration = if (totalDuration == 0) duration else totalDuration.min(duration)   
    }

    val pw = new PrintWriter(new FileOutputStream(new File(logFile),true)) 
    pw.write(description + " " + result + " " + totalDuration +" ms"+"\n")
    pw.flush()
    pw.close
}

在上面的代码中,我正在计算我的结果,其中包含从其他函数读取的字节长度,并希望计算读取总字节所需的时间。我想迭代3次并取三者中的最小值。 val结果包含字节长度,也需要在文件中写入。我得到一个错误,因为我正在访问for循环范围之外的结果val。有人可以帮我解决这个错误。如何在for循环中访问val结果以将其写入文件?

提前致谢!!

4 个答案:

答案 0 :(得分:0)

您可以使用收益。在完成循环后,Yield将从for循环返回数据并相应地使用该数据。因为我没有你的代码。看这个例子

$(OBJS)

j的输出将是

val j = for (i <- 1 to 10) yield i
println(j)

答案 1 :(得分:0)

要替换for循环以计算按顺序执行的某些作业的总持续时间,您可以使用foldLeft

答案 2 :(得分:0)

利用收益率或您可以使用任何折叠方法。或者如果你对递归很好,你可以使用tailrec方法返回Desired。产量是最简单的方法。

val answer = for(i<- 1 to 10) yield i 
println(answer) // Vector(1,2,3,4,5,6,7,8,9,10)

答案 3 :(得分:0)

当您的问题得到解答时,for循环不是典型的形式,看起来更像是这样:

def time[A] (logFile: String, description: String) (job: => A): Unit = {
    val (result, totalDuration): (A, Long) = (for { i <- 1 to 3 
        currentTime = System.currentTimeMillis
        result = job
        finalTime = System.currentTimeMillis
        duration = finalTime - currentTime 
    } yield (result, duration)).minBy {case (r, d) => d} 

    val pw = new PrintWriter (new FileOutputStream (new File (logFile), true)) 
    pw.write (description + " " + result + " " + totalDuration +" ms"+"\n")
    pw.flush()
    pw.close
}

如果我正确理解您的代码。我不知道副作用是否会导致每个作业调用的结果不同。 我错过了for-loop发明/定义的内部讨论,为什么这里应该省略关键字val,但它很安静。

更重要的是,您通常在for (...(here part)...) { not here}中拥有所有临时任务。第一部分中圆形或花括号的后果对我来说并不完全清楚,但如果使用圆形括号,则可以用分号终止大多数语句。

scala> for (i <-  1 to 3;
     | j <- 4 to 5;
     | k = j-i;
     | l = k/2) yield l * l; 
res2: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 4, 1, 1, 0, 1)

注意i,j,k,l都没有声明为val或var。

scala> for {i <-  1 to 3
     | j <- 4 to 5
     | k = j-i
     | l = k/2} yield l * l; 
res3: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 4, 1, 1, 0, 1)

你会在这里找到多个问题,它们解释了for循环是如何并且可以转换为flatMap / map-combination,最终使用filter:

scala> for {i <-  1 to 3
     | j <- 4 to 5
     | k = j-i
     | if (k > 1) 
     | l = k/2 } yield l * l; 
res5: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 4, 1, 1, 1)

而不是只产生一个值,你可以产生一个元组,并通过

分配
 val (a:X, b:Y) = (for ..... yield (aa, bb)) 

yield (result, duration)).minBy {case (r, d) => d}

取一个元组(结果,持续时间)并按持续时间选择最小值,但产生两个值。