Deb*_*ski 1 iterator functional-programming scala count immutability
如果我想枚举Scala中内循环的迭代,我将如何以函数式方式处理它?
例如,我将如何重写以下代码:
val documents = List("a" :: "b" :: Nil, "aa" :: "bb" :: Nil, "aaa" :: Nil)
var currentPageNumber = 0
documents.foreach { doc =>
for (page <- doc) {
currentPageNumber += 1
println("%d: %s".format(currentPageNumber.head, page)
// do something with page
}
}
Run Code Online (Sandbox Code Playgroud)
我可以摆脱var使用val currentPageNumber = Iterator.from(0)但这仍然意味着我实际上需要在循环之外声明它.
有没有一个技巧不会暴露currentPageNumber到外部范围 - 就像zipWithIndex计数器一样 - 只存在于循环内部?
编辑:
我也发现了一个版本,scanLeft但我觉得它很混乱.但也许有人可以以某种方式优化它.
documents.scanLeft(0) { case (cnt, doc) =>
doc.zip(Iterator.from(cnt + 1).toIterable).map { case(page, cnt) =>
println("%d: %s".format(cnt, page))
cnt
} last
}
Run Code Online (Sandbox Code Playgroud)
自己的解决方案(现在):
谢谢大家,我想我的想法是这样的
documents.flatMap{ doc =>
for (page <- doc) yield {
currentPageNumber: Int =>
"%d: %s".format(currentPageNumber, page)
}}.zipWithIndex.map (t => t._1(t._2 + 1)) map(println)
Run Code Online (Sandbox Code Playgroud)
所以,诀窍是currentPageNumber不确定,直到可以实际应用zipWithIndex.
我认为你使用的命令式版本可能更好,因为printf无论如何都有副作用,但如果你想要一些功能,你可以这样做:
documents.foldLeft(1){ (docStartingPage,doc) =>
doc.foldLeft(docStartingPage){ (currentPageNumber, page) =>
printf("%d: %s\n", currentPageNumber, page)
currentPageNumber + 1
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,如果外部循环中的数字将再次出现在内部循环中,则该数字必须可用.
您也可以尝试以下操作,但是您将丢失有关文档开始和结束位置的任何信息.
for ( (page,pageNumber) <- documents.flatten.zipWithIndex )
printf("%d: %s\n", pageNumber + 1, page)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5890 次 |
| 最近记录: |