67

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

class Foo {
   String bar
}

现在想象我有几个实例,Foobar值为baz_1,baz_2zab_3

我想写一个只收集bar包含文本的值的收集语句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' ]
4

3 回答 3

100

你需要findAll

barsOfAllFoos.findAll { it.contains 'baz' }
于 2012-10-12T20:40:09.740 回答
52

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

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

final barsWithBaz = barsOfAllFoos.findResults {
    it.contains('baz')? frob(it) : null
}

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

final barsWithBaz = barsOfAllFoos
                  . findAll { it.contains('baz') }
                  . collect { frob(it) }

或者#sum

final barsWithBaz = barsOfAllFoos.sum([]) {
    it.contains('baz')? [frob(it)] : []
}

或者#inject

final barsWithBaz = barsOfAllFoos.inject([]) {
    l, it -> it.contains('baz')? l << frob(it) : l
}
于 2012-10-12T23:21:31.413 回答
1

使用findResults对我不起作用...如果您想收集与条件匹配的值的转换版本(例如多行的正则表达式搜索),您可以使用collect后跟findfindAll如下。

def html = """
    <p>this is some example data</p>
    <script type='text/javascript'>
        form.action = 'http://www.example.com/'
        // ...
    </script>
"""

println("Getting url from html...")
// Extract the url needed to upload the form
def url = html.split("\n").collect{line->
    def m = line =~/.*form\.action = '(.+)'.*/
    if (m.matches()) {
        println "Match found!"
        return m[0][1]
    }
}.find()

println "url = '${url}'"

这将返回与给定模式匹配的行部分。

Getting url from html...
Match found!
url = 'http://www.example.com/'
于 2016-05-27T15:01:25.310 回答