Grails 如何使用递归闭包从groovy中的列表构建树层次结构?

Grails 如何使用递归闭包从groovy中的列表构建树层次结构?,grails,groovy,closures,Grails,Groovy,Closures,我在grails中定义了递归域类: class Work { String code String title String description static hasMany = [subWorks:Work] static mappedBy = [subWorks: 'parentWork'] Work getRootWork(){ if(parentWork) return parentWork.getRootWork() else ret

我在grails中定义了递归域类:

class Work {

  String code
  String title
  String description
  static hasMany = [subWorks:Work]
  static mappedBy = [subWorks: 'parentWork']

  Work getRootWork(){
    if(parentWork) return parentWork.getRootWork()
      else return this
  }

  boolean isLeafWork(){
    return subWorks.isEmpty()
  }

  boolean isRootWork(){
    return !parentWork
  }
我有一个作品列表,但是层次结构还没有建立。结构如下所示:

def works = [new Work(code:'A', title:'TitleA'), 
    new Work(code:'B', title:'TitleB'), 
    new Work(code:'A.1', title:'Titile A.1'), 
    new Work(code:'B.1', title:'Title B.1'),
    new Work(code:'B.2', title:'Title B.2'),
    new Work(code:'B.3', title:'Title B.3'), 
    new Work(code:'B.2.2', title:'Title B.2.2'),
    new Work(code:'B.2.3', title:'Title B.2.3'),
    new Work(code:'A.1.1', title:'Title A.1.1'),
    new Work(code:'A.1.2', title:'Title A.1.2'),]
我需要的是根据暗示的代码在这些作品之间建立层次关系。e、 g.A.1是A的第一个儿童作品;B.1.1是B.1工作的第一个子项,其父项为B工作。我知道Groovy支持递归闭包来构建这种层次结构。如何在Groovy官方文档中使用Groovy递归闭包(如JN2515 Fibonacci数示例)实现我的目标? 非常感谢

像这样

def root = new Work(code:'*', title:'ROOT')

def build 

build = { p, list ->
  list.groupBy{it.code.split('\\.').first()}.each{ el, sublist ->
    el = sublist[0]        
    el.parentWork = p
    if(sublist.size()>1){
        build(el, sublist[1..-1] )
    }
  }

}
build(root, works.sort{it.code.length()})
如果我没有犯错误,即使是在这种情况下,我也可以工作

def root = new Work(code:'*', title:'ROOT')

{ p, list ->
  list.groupBy{it.code.split('\\.').first()}.each{ el, sublist ->
    el = sublist[0]        
    el.parentWork = p
    if(sublist.size()>1){
      call(el, sublist[1..-1] )
    }
  }

}(root, works.sort{it.code.length()})

我对Grails有点生疏,但我似乎记得它以智能的方式管理映射集合,因此如果您这样做:
work1.parentWork=work2
,那么
work2中的work1.subWorks
将进行验证。如果是这种情况,您只需为每个工作设置
父工作
,而无需为此进行任何复杂的计算:
X.Y.Z
的父工作将是
X.Y
,而
X
的父工作将是无:

def works = [new Work(code:'A', title:'TitleA'),
    new Work(code:'B', title:'TitleB'),
    new Work(code:'A.1', title:'Titile A.1'),
    new Work(code:'B.1', title:'Title B.1'),
    new Work(code:'A.1.1', title:'Title A.1.1')]

def worksByCode = works.collectEntries { [it.code, it] }

works.each {
    if (it.code.contains('.')) {
        def parentCode = it.code[0..it.code.lastIndexOf('.') - 1]
        it.parentWork = worksByCode[parentCode]
    }
}

非常感谢开明的代码。以上代码适用于示例列表:works。如果我需要A.1.2属于A.1的工作怎么办;A.2.2工作是A.2的第二个孩子吗?只要稍微修改一下我的问题。如果你想让子作品有序,你必须改变你的数据结构。看这里。我想你想在工作课上使用SortedSet并实现compareTo方法。它看起来也非常棒!