Как вы делаете вложенные итераторы в groovy?

18

Поддерживает ли groovy какое-либо вложенное обозначение итератора?

В приведенном ниже примере я хочу как-то получить значение projectName, которое исходило из внешнего итератора, в мой внутренний итератор. Возможно ли это без сохранения в переменной? В моем примере я получаю ошибку runtuime, что «проект» не найден.

it.myprojects.project.each{
     println("Project name: " + it.projectName)
    it.myroles.role.each{
         Role role = new Role()
             role.setName(project.projectName)//how do I get projectName here without storting it in a variable in the outer loop?
    }
}
    
задан Derek 24.09.2010 в 19:18
источник

3 ответа

18

Кажется, что это должно работать:

it.myprojects.project.each{ project->
     println("Project name: " + project.projectName)
     it.myroles.role.each{
         Role role = new Role()
         role.setName(project.projectName)
    }
}

Кроме того, вы можете ссылаться на внешнее закрытие, используя переменную owner

it.myprojects.project.each{ 
     println("Project name: " + it.projectName)
     it.myroles.role.each{
         Role role = new Role()
             role.setName(owner.projectName)
    }
}

Однако я не вижу причины для повторения роли, если все, что вы, кажется, делаете, это создание новых экземпляров класса Role. Возможно, что-то вроде этого будет проще:

it.myprojects.project.each{ 
     println("Project name: " + it.projectName)
     it.myroles.role.size().times {
         Role role = new Role()
         role.setName(owner.projectName)
    }
}
    
ответ дан mfloryan 25.09.2010 в 00:09
источник
  • +1 и выбрано для ответа на вопрос, который я задал –  Derek 27.09.2010 в 15:35
  • Вы также можете указать класс именованного итератора, если ваша IDE не может понять его, например: it.myprojects.project.each {Проект проекта -> ... Иногда мне нравится делать это для автозаполнения и , Возможно, это загрязняет ваш код без необходимости для вашей поддержки IDE, но он есть, если вы этого хотите. –  Charles Wood 18.12.2014 в 17:52
27

Эти переменные it являются not итераторами, это параметры закрытия . Имя it не является сокращенным для «итератора», оно буквально означает «оно», которое используется как имя по умолчанию для однопараметрических закрытий. Однако вы можете использовать явные (и, следовательно, разные вложенные) имена, такие как:

it.myprojects.project.each{ project ->
     println("Project name: " + project.projectName)
     project.myroles.role.each{ role->
         Role r= new Role()
         r.setName(project.projectName)
    }
}

На самом деле, я бы посоветовал не использовать метод each и вместо этого использовать реальные циклы:

for(project in it.myprojects.project){
     println("Project name: " + project.projectName)
     for(role in project.myroles.role){
         Role r= new Role()
         r.setName(project.projectName)
    }
}

Это лучше, потому что закрытие делает код намного сложнее отлаживать, а также потенциально медленнее. И в этом случае, в любом случае, нет никакого преимущества в использовании закрытий.

    
ответ дан Michael Borgwardt 24.09.2010 в 19:31
источник
  • ах - это сбивает с толку. Код определенно работает, если вы продолжаете повторное использование «it» вложенным образом. Мне стало ясно, что было что-то смешное, когда я пытался сделать обратную ссылку на предыдущую –  Derek 24.09.2010 в 19:36
  • @Derek: Похоже, вы занимаетесь программированием на основе грузов, т. е. пытаетесь использовать синтаксис, не понимая, что это значит. Неудивительно, что вы в замешательстве. Вам действительно нужно читать закрытие, пока не поймете, что «каждый» - это метод, а не ключевое слово языка, код в фигурных скобках - это закрытие, переданное как параметр методу, а «it» - неявный параметр закрытие, когда оно вызывается каждым методом. –  Michael Borgwardt 24.09.2010 в 19:42
  • Я не понимаю, почему явный цикл будет лучше, чем использование каждого метода - это скорее случай личного стиля и предпочтения. –  mfloryan 25.09.2010 в 00:12
  • @mfloryan: Вы бы не сказали, что если бы вы когда-либо видели трассировку стека, брошенную внутри трижды вложенного закрытия. Они могут быть синтаксически изящными, но на JVM (по крайней мере прямо сейчас) им требуются очень сложные хаки, которые раздувают байтовый код и трассировку стека, и какие отладчики (по крайней мере, в затмении) не могут справиться хорошо. –  Michael Borgwardt 25.09.2010 в 10:15
  • ОК. Я согласен в этом конкретном случае, что детали реализации на низком уровне действительно имеют значение (и да, я видел такие трассировки стека и декомпилировал байт-код, поэтому у меня есть приблизительное представление о том, как оно выглядит). Тем не менее, это всего лишь временная проблема и, вероятно, имеет незначительные последствия для производительности, но дает более выразительный и чистый код. –  mfloryan 26.09.2010 в 16:47
0
 it.projectList.each {...}

?

и это: Ссылка .

Вы зацикливаете на списке, а не на вещи в списке. Кажется, из вашего кода вы зацикливаете на предмет в списке.

    
ответ дан hvgotcodes 24.09.2010 в 19:22
источник
  • err, thats my bad в синтаксисе. Я действительно вытаскиваю это из файла XML, и у меня есть некоторые теги, называемые «список проектов» и «список роли», поэтому список слов - это просто совпадение –  Derek 24.09.2010 в 19:26
  • теперь редактировал код, поэтому нет путаницы –  Derek 24.09.2010 в 19:28
  • @derek есть проблема? Запустите его в своем любимом отладчике и посмотрите, какой проект ... так же, я заметил, что первый токен в вашем коде - это «он», поэтому кажется, что некоторые вещи происходят вне кода, который вы опубликовали, что вы, возможно, захотите доля. –  hvgotcodes 24.09.2010 в 19:32
  • @Derek: отредактированный код по-прежнему выглядит неправильно - если myprojects представляет собой набор проектов, то каждое закрытие должно быть применено к этой коллекции –  Michael Borgwardt 24.09.2010 в 19:35