代码之家  ›  专栏  ›  技术社区  ›  bsr

groovy中的递归(grails)

  •  4
  • bsr  · 技术社区  · 14 年前

    我尝试在groovy中使用递归遍历树关系。下面的代码运行一个周期,直到childNodes&&recurClosure(childNodes),但不再调用闭包recurClosure。此时,childNodes有两个与root类型相同的对象(数组列表)。

    在代码中,定义了recurClosure,并使用对象列表(根)调用它。然后它遍历每个元素并细化子节点(为此使用grailsdsl)。

    我应该分手,还是怎么了?

    def parentval 
    def root = Domain.list()
    
    def recurClosure
    recurClosure = {inroot ->
      inroot.each {
        returnList << it
        parentval = it
        childNodes = Domain.withCriteria {
          eq('parent', parentval )
        }
      }
      childNodes && recurClosure(childNodes )
    }(root)
    
    return returnList
    

    更新:注意到以下异常

        ERROR [2010-06-24 08:20:04,742] [groovy.grails.web.errors.GrailsExceptionResolver] Cannot invoke method call() on null object
    java.lang.NullPointerException: Cannot invoke method call() on null object
        at com.bsr.test.DomainService$_closure2_closure7.doCall(com.bsr.test.DomainService:68)
        at com.bsr.test.DomainService$_closure2.doCall(com.bsr.test.DomainService:58)
        at com.bsr.test.DomainController$_closure3.doCall(DomainController.groovy:45)
        at com.bsr.test.DomainController$_closure3.doCall(DomainController.groovy)
        at org.apache.shiro.web.servlet.ShiroFilter.executeChain(ShiroFilter.java:687)
        at org.apache.shiro.web.servlet.ShiroFilter.doFilterInternal(ShiroFilter.java:616)
        at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:81)
        at java.lang.Thread.run(Thread.java:619)
    

    更新2:现在尝试丹尼尔的建议。

    { inroot ->
        inroot.each {
            returnList << it
            parentval = it
            childNodes = Domain.withCriteria {
                eq('parent', parentval )
            }
               if(childNodes)
               call(childNodes)
        }
           /*if(childNodes)
            call(childNodes)*/
    
    }(root)
    

    ERROR [2010-06-24 08:47:46,438] [groovy.grails.web.errors.GrailsExceptionResolver] instance not of expected entity type: java.util.ArrayList is not a: com.bsr.test.Domain
    

    我看到一篇关于如何命名关闭的博客文章 'this'

    更新3:调用外部闭包的方法是owner.call(childNodes)

    2 回复  |  直到 14 年前
        1
  •  10
  •   Daniel Rinser    14 年前

    问题是

    recurClosure = {
        [...]
    }(root)
    

    你没有把闭包分配给 recurClosure 返回值 recurClosure() ...

    首先定义闭包,然后单独调用它,正如air\u blob建议的那样:

    def recurClosure = {
        [...]
    }
    recurClosure(root)
    

    使用隐式 call() 递归函数。这样,您甚至可以使用匿名闭包。在Groovy中实现递归的一个非常好的方法是:

    { inroot ->
        inroot.each {
            returnList << it
            parentval = it
            childNodes = Domain.withCriteria {
                eq('parent', parentval )
            }
        }
        if(childNodes)
            call(childNodes)
    }(root)
    

    您的代码还有两条注释:

    1. 你可以申报 returnList : def returnList = []
    2. childNodes && recurClosure(childNodes ) 你想怎么做就怎么做,多牺牲一个字符,拼出 if
    3. 你不想递归地调用你的闭包吗 里面 each ?

    Domain ),不会 Domain.list() 真的把孩子也都还了吗?真的需要手动遍历树吗?

        2
  •  2
  •   codeporn    14 年前

    有例外吗? 您是否尝试过这样单独调用它:

    def recurClosure
    recurClosure = {inroot ->
      [... stuff ...]
    }
    
    recurClosure(root)
    

    在这行你到底想做什么:

    childNodes && recurClosure(childNodes )