2013-04-12 33 views
5

tôi xác định các lớp miền đệ quy trong grails:làm thế nào để xây dựng một hệ thống phân cấp cây từ danh sách trong groovy bằng cách sử dụng đệ quy đóng cửa?

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 
    } 

Tôi có một danh sách các công trình, nhưng cấu trúc hệ thống phân cấp không được xây dựng được nêu ra. Cấu trúc trông giống như:

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'),] 

Điều tôi cần là xây dựng mối quan hệ phân cấp giữa các tác phẩm này, dựa trên mã được gợi ý. ví dụ. A.1 là công việc con đầu tiên của A; B.1.1 là đứa con đầu tiên của công việc B.1, có cha mẹ là B làm việc. Tôi biết rằng Groovy hỗ trợ đóng cửa đệ quy để xây dựng loại cấu trúc phân cấp này. Làm thế nào để đạt được mục tiêu của tôi bằng cách sử dụng Groovy đệ quy đóng cửa, chẳng hạn như ví dụ số Fibonacci JN2515, trong tài liệu chính thức Groovy? Rất cám ơn!

Trả lời

3

như thế này ...?

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

nếu như tôi không do lỗi ngay cả trong hình thức Anonim này có thể làm việc

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()}) 
+0

Rất cảm ơn mã đã khai sáng. Đoạn mã trên hoạt động cho danh sách mẫu: công trình. Điều gì xảy ra nếu tôi cần A.1.2 công việc thuộc về A.1; A.2.2 công việc là đứa con thứ hai của A.2? Chỉ cần chỉnh sửa một chút câu hỏi của tôi. –

+0

Nếu bạn muốn subWorks theo kiểu đặt hàng, bạn phải thay đổi cấu trúc dữ liệu của mình. Xem tại đây, http://grails.org/doc/latest/guide/GORM.html#sets,ListsAndMaps. Tôi nghĩ bạn muốn sử dụng SortedSet và thực hiện phương thức compareTo trong lớp Work. –

1

Tôi là một chút gỉ với Grails, nhưng tôi dường như nhớ rằng nó được quản lý ánh xạ bộ sưu tập một cách thông minh , nếu bạn làm như vậy: work1.parentWork = work2 thì work1 in work2.subWorks sẽ xác minh. Nếu trường hợp đó xảy ra, tất cả những gì bạn cần làm là đặt parentWork cho mọi công việc và bạn không cần thực hiện bất kỳ phép tính phức tạp nào cho công việc này: công việc gốc của X.Y.Z sẽ là X.Y và công việc của cha mẹ là X sẽ không có :

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] 
    } 
} 
+0

Trông nó cũng rất rực rỡ! –

Các vấn đề liên quan