有没有办法在Scala for循环中以不同方式处理最后一种情况?

del*_*ber 16 scala

例如,假设我有

  for (line <- myData) {
    println("}, {")
  }
Run Code Online (Sandbox Code Playgroud)

有没有办法让最后一行打印

println("}")
Run Code Online (Sandbox Code Playgroud)

Tom*_*icz 28

你能重构你的代码以利用内置的mkString吗?

scala> List(1, 2, 3).mkString("{", "}, {", "}")
res1: String = {1}, {2}, {3}
Run Code Online (Sandbox Code Playgroud)


Kev*_*ght 19

在继续之前,我建议你避免println进行理解.它有时可用于跟踪集合中间发生的错误,但否则会导致难以重构和测试的代码.

更一般地说,如果你可以限制发生任何副作用的地方,生活通常会变得更容易.所以代替:

for (line <- myData) {
  println("}, {")
}
Run Code Online (Sandbox Code Playgroud)

你可以写:

val lines = for (line <- myData) yield "}, {"
println(lines mkString "\n")
Run Code Online (Sandbox Code Playgroud)

我也想在这里猜测你想要输出中每一行的内容!

val lines = for (line <- myData) yield (line + "}, {")
println(lines mkString "\n")
Run Code Online (Sandbox Code Playgroud)

如果你只是mkString直接使用,你会感觉更好- 这就是它的用途!

val lines = myData.mkString("{", "\n}, {", "}")
println(lines)
Run Code Online (Sandbox Code Playgroud)

请注意我们如何首先生成a String,然后在单个操作中打印它.这种方法可以很容易地分成单独的方法,用于toString在类上实现,或者在测试中检查生成的String.


Did*_*ont 13

我完全赞同之前所说的关于使用mkstring和区分第一次迭代而不是最后一次迭代的内容.你还需要区分最后,scala集合有一个init方法,它返回所有元素,但最后一个.所以你可以做到

for(x <- coll.init) workOnNonLast(x)
workOnLast(coll.last)
Run Code Online (Sandbox Code Playgroud)

(init并且last与头部和尾部相反,这是第一个,而且是第一个).但是请注意,取决于结构,它们可能是昂贵的.在Vector,所有这些都很快.在List,虽然头部和尾部基本上是自由的,init并且last在列表的长度上都是线性的.当集合可能为空时headOption,lastOption可以帮助您,替换workOnlast

for (x <- coll.lastOption) workOnLast(x)
Run Code Online (Sandbox Code Playgroud)


Nic*_*las 6

您可以将trait 的addString函数TraversableOnce作为示例.

def addString(b: StringBuilder, start: String, sep: String, end: String): StringBuilder = {
  var first = true

  b append start   
  for (x <- self) {
    if (first) {
      b append x
      first = false
    } else {
      b append sep
      b append x
    }
  }
  b append end

  b
}
Run Code Online (Sandbox Code Playgroud)

在您的情况下,分隔符是}, {和结束}