Есть ли способ использовать метод сбора Groovy в сочетании с другой функцией итератора? - PullRequest
1 голос
/ 27 декабря 2011

Например, класс groovy File имеет приятный итератор, который отфильтровывает только каталоги, а не файлы:

void eachDir(Closure closure) 

Когда я использую eachDir, я должен использоватьподробный метод первого создания коллекции и добавления к ней:

def collection = []    
dir1.eachDir { dir ->
  collection << dir
}

Есть ли способ вернуть ее к хорошему синтаксису компактного сбора?

Ответы [ 2 ]

3 голосов
/ 27 декабря 2011

Я не знаю ни одного "идиоматического" способа сделать это, хорошая загадка!= 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 голос
/ 27 декабря 2011

Не для конкретного примера, о котором вы говорите.File.eachDir - своего рода странная реализация IMO.Было бы неплохо, если бы они реализовали iterator () для File, чтобы вы могли использовать обычные методы итератора для них, а не пользовательские методы, которые просто выполняют замыкание.

Самый простойспособ получить чистый лайнер, который делает то, что вам нужно, это использовать listFiles вместо этого в сочетании с findAll:

dir1.listFiles().findAll { it.directory }

Если вы посмотрите на реализацию eachDir, вы увидите, что он делает это(и многое другое, что вас не волнует в данном случае) под прикрытием.

Для многих подобных ситуаций, инъекция - это метод, который вы ищете, чтобы иметь начальное значение, которое выизменить при переборе коллекции:

def sum = [1, 2, 3, 4, 5].inject(0) { total, elem -> total + elem }
assert 15 == sum
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...