例如,groovy File类有一个很好的迭代器,它只会过滤目录而不是文件:
void eachDir(Closure closure)
当我使用eachDir
时,我必须先使用详细的方法创建集合并附加到它:
def collection = []
dir1.eachDir { dir ->
collection << dir
}
任何方式让它回到漂亮的紧凑收集语法?
答案 0 :(得分:3)
我不知道这样做的任何“惯用”方式,很好的谜语! = d
您可以尝试将eachDir
或任何类似函数传递给将收集其迭代的函数:
def collectIterations(fn) {
def col = []
fn {
col << it
}
col
}
现在您可以将其用作:
def dir = new File('/path/to/some/dir')
def subDirs = collectIterations(dir.&eachDir)
def file = new File('/path/to/some/file')
def lines = collectIterations(file.&eachLine)
(最后一个例子相当于file.readLines()
)
只有奖励积分,您可以将此功能定义为Closure
类中的方法:
Closure.metaClass.collectIterations = {->
def col = []
delegate.call {
col << it
}
col
}
def dir = new File('/path/to/some/dir')
def subDirs = dir.&eachDir.collectIterations()
def file = new File('/path/to/some/file')
def lines = file.&eachLine.collectIterations()
更新:另一方面,您可能也会这样做:
def col = []
someDir.eachDir col.&add
我认为这个问题相当复杂,但并没有按照您的要求利用collect
方法:)
答案 1 :(得分:1)
不是您所谈论的具体示例。 File.eachDir是一种奇怪的实现IMO。如果他们在File上实现iterator()以便你可以use the normal iterator methods在它们上而不是只执行闭包的自定义构建的那个就好了。
最简单的方法是获得一个干净的单行程,以满足您的需求,使用listFiles代替findAll:
dir1.listFiles().findAll { it.directory }
如果你看一下eachDir的实现,你会发现它正在做这个(并且你不关心这个实例的更多内容)。
对于许多类似的情况,inject是您正在寻找的方法,以便在迭代集合时更改起始值:
def sum = [1, 2, 3, 4, 5].inject(0) { total, elem -> total + elem }
assert 15 == sum