如何在groovy中编写条件集合?

ubi*_*con 62 groovy

想象一下,我有这样的结构:

class Foo {
   String bar
}
Run Code Online (Sandbox Code Playgroud)

现在想象一下,我有几个实例Foo,其bar值是baz_1,baz_2zab_3.

我想编写一个只收集bar包含文本的值的collect语句baz.我无法让它工作,但它看起来像这样:

def barsOfAllFoos = Foo.getAll().bar
assert barsOfAllFoos == [ 'baz_1', 'baz_2', 'zab_3' ]
def barsWithBaz = barsOfAllFoos.collect{ if( it.contains( "baz" ) { it } ) } // What is the correct syntax for this?
assert barsWithBaz == [ 'baz_1', 'baz_2' ]
Run Code Online (Sandbox Code Playgroud)

tim*_*tes 95

你需要findAll:

barsOfAllFoos.findAll { it.contains 'baz' }
Run Code Online (Sandbox Code Playgroud)

  • 如果你想一步过滤和转换,那就是`collectMany`. (23认同)
  • 我想@Justin_Piper在这里得到了最好的答案.与`findResults`相比,使用collectMany是笨重的 (2认同)

Jus*_*per 45

如果你想过滤和转换,有很多方法可以做到这一点.在1.8.1之后,我会使用#findResults一个闭包,它为我想要跳过的元素返回null.

def frob(final it) { "frobbed $it" }

final barsWithBaz = barsOfAllFoos.findResults {
    it.contains('baz')? frob(it) : null
}
Run Code Online (Sandbox Code Playgroud)

在早期版本中,您可以使用#findAll#collect

final barsWithBaz = barsOfAllFoos
                  . findAll { it.contains('baz') }
                  . collect { frob(it) }
Run Code Online (Sandbox Code Playgroud)

要么 #sum

final barsWithBaz = barsOfAllFoos.sum([]) {
    it.contains('baz')? [frob(it)] : []
}
Run Code Online (Sandbox Code Playgroud)

要么 #inject

final barsWithBaz = barsOfAllFoos.inject([]) {
    l, it -> it.contains('baz')? l << frob(it) : l
}
Run Code Online (Sandbox Code Playgroud)