【问题标题】:How do you do nested iterators in groovy?你如何在groovy中做嵌套迭代器?
【发布时间】:2010-09-24 17:18:22
【问题描述】:

groovy 是否支持任何类型的嵌套迭代器表示法?

在下面的示例中,我想以某种方式将来自外部迭代器的 projectName 值获取到我的内部迭代器中。如果不存储在变量中,这可能吗?在我的示例中,我收到一个运行时错误,即找不到“项目”

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?
    }
}

【问题讨论】:

    标签: loops groovy iterator


    【解决方案1】:

    那些it 变量是不是 迭代器,它们是closure 参数。名称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)
        }
    }
    

    这更好,因为闭包使代码更难调试,而且可能更慢。在这种情况下,无论如何使用闭包并没有任何优势。

    【讨论】:

    • 啊——这令人困惑。如果您继续以嵌套方式重复使用“它”,则该代码肯定有效。当我试图对前一个进行反向引用时,我才发现发生了一些有趣的事情
    • @Derek:听起来你在做货物狂热的编程,即尝试使用语法而不理解它的含义。难怪你会感到困惑。您确实需要阅读闭包,直到您了解“每个”是一种方法,而不是语言关键字,花括号中的代码是作为参数传递给该方法的闭包,而“它”是隐式参数每个方法调用时的闭包。
    • 我不明白为什么显式循环会比使用 each 方法更好 - 它更多的是个人风格和偏好。
    • @mfloryan:如果您曾经看到在三次嵌套的闭包中抛出堆栈跟踪,您就不会这么说。它们在语法上可能很优雅,但在 JVM 上(至少现在是这样),它们需要非常复杂的 hack,导致字节码和堆栈跟踪膨胀,而调试器(至少是 eclipse 中的调试器)不能很好地处理。
    • 好的。我同意在这种特殊情况下,低级实现细节确实有所作为(是的,我已经看到了这样的堆栈跟踪并且已经反编译了字节码,所以我大致了解它的样子)。这仍然只是一个暂时性问题,可能对性能的影响可以忽略不计,但可以让代码更具表现力和更简洁。
    【解决方案2】:

    感觉这应该可行:

    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)
        }
    }
    

    【讨论】:

    • 如果您的 IDE 无法识别,您也可以指定命名迭代器的类,例如:it.myprojects.project.each { Project project -> ... 有时我喜欢这样做是为了自动完成等。可以说,这会不必要地污染您的代码,以使您的 IDE 受益,但如果您需要,它就在那里。
    【解决方案3】:
     it.projectList.each {...}
    

    ?

    还有这个:http://groovy.codehaus.org/Looping

    您在列表中循环,而不是在列表中的事物上。从您的代码看来,您正在循环列表中的内容。

    【讨论】:

    • err,那是我的语法错误..我实际上是从 XML 文件中提取它,并且我有一些名为“projectlist”和“rolelist”的标签,所以单词列表只是一个巧合跨度>
    • @derek 还有问题吗?在你最喜欢的调试器中启动它,看看是什么项目......另外,我注意到你的代码中的第一个标记是“它”,所以看起来在你发布的代码之外还有一些你可能想要的东西分享。
    • @Derek:编辑后的代码 still 看起来不对 - 如果 myprojects 是项目的集合,那么每个闭包都应该应用于该集合
    猜你喜欢
    • 2012-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多