Как написать условный сбор в groovy?


представьте, что у меня есть такая структура:

class Foo {
   String bar
}

теперь представьте, что у меня есть несколько экземпляров Foo чей bar значение baz_1,baz_2 и zab_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' ]
3 59

3 ответа:

вам нужно findAll:

barsOfAllFoos.findAll { it.contains 'baz' }

если вы хотите фильтровать и преобразовывать существует много способов сделать это. После 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
}

используя findResults не работает для меня... Если вы хотите собрать преобразованную версию значений, соответствующих условию (например, поиск регулярных выражений по многим строкам), вы можете использовать collect следовал по find или findAll следующим образом.

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/'