如果我使用stdin
处理scanLeft
的输入,则结果输出始终在最后输入的后面一行:
io.Source.stdin
.getLines
.scanLeft("START:")((accu, line) => accu + " " + line)
.foreach(println(_))
结果(在我的手动输入之前为
>
):> first
START:
> second
START: first
> third
START: first second
我想要的明智的输出是:
> first
START: first
> second
START: first second
> third
START: first second third
如您所见,第一输入行之后的输出应该已经包含第一输入行的字符串。
我已经使用
.scanLeft(...).drop(1).foreach(...)
尝试过,但这导致以下结果:> first
> second
START: first
> third
START: first second
如何正确省略纯种子以获得所需的结果?
[更新]
目前,我对Andrey Tyukin的巧妙解决方法感到满意。非常感谢您提出建议。
但是,当然,如果
scanLeft
有任何替代选择,并且不将种子作为第一项发送到以下迭代链中,我将更喜欢该解决方案。 [更新]
jwvh用户理解了我的目标,并为此提供了出色的解决方案。为了完善他们的建议,我寻求一种预处理行的方法,然后将它们发送到累积回调中。因此,不应在累积回调中调用
readLine
命令,而应在其他链链接中调用。 最佳答案
您可以用Stream.iterate()
代替scanLeft()
并用StdIn.readLine
代替stdin.getLines
来获得非常相似的东西。
def input = Stream.iterate("START:"){prev =>
val next = s"$prev ${io.StdIn.readLine}"
println(next)
next
}
由于
Stream
的计算是惰性的,因此您需要一些方法来实现它。val inStr = input.takeWhile(! _.contains("quit")).last
START: one //after input "one"<return>
START: one two //after input "two"<return>
START: one two brit //after input "brit"<return>
START: one two brit quit //after input "quit"<return>
//inStr: String = START: one two brit
如果确实需要,您实际上不必放弃
getLines
迭代器。def inItr = io.Source.stdin.getLines
def input = Stream.iterate("START:"){prev =>
val next = s"$prev ${inItr.next}"
println(next)
next
}
不知道这是否解决您的评论。很多情况取决于可能来自何处的错误以及如何确定错误。
Stream.iterate(document()){ doc =>
val line = io.StdIn.readLine //blocks here
.trim
.filterNot(_.isControl)
//other String or Char manipulations
doc.update(line)
/* at this point you have both input line and updated document to play with */
... //handle error and logging requirements
doc //for the next iteration
}
我假设
.update()
修改了源文档,但未返回任何内容(返回Unit
)。这是update()
方法的常用签名。其中大部分可以在调用链中完成(
_.method1.method2.
等),但有时这会使事情变得更复杂。通过使用称为kestrel pattern的方法,仍可以将未返回感兴趣值的方法添加到调用链中。
关于Scala:从stdin读取时,scanLeft落后一项,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49417774/