神奇的Grails:自关联的树状Domain一行代码获取所有子节点

见证Groovy/Grails的神奇时刻到了,你相信吗?用一行代码就可以获取树状结构中某节点下的所有全部子节点!注意:这个树是无深度限制的。无深度限制这点很重要,如果有限深度的树,那我们也很容易通过层级编码用“Like 001%”方式实现(维护编码也是一个有挑战性活)。我们以一个非常常见的“类别”Domain为例,大类分小类,小类再细分,典型的树形结构,看看Grails是如何以简洁的语法表达的,体验Groovy语法的神奇!

class Group{
    String name

    static hasMany = [children:Group]
    static belongsTo = [parent: Group]

    static transients = [‘allChildren‘]

    def getAllChildren(){
        children ? children + children*.allChildren.flatten() : []
    }
}

1.两行代码表述一个树状结构,同时Grails自动为你生成数据库表

static hasMany = [children:Group]
static belongsTo = [parent: Group]

2.一行代码获取任意深度的全部子节点:

children ? children + children*.allChildren.flatten() : []

递归调用这个是必须的*.allChildren.flatten()。

短短一行代码,展现了五个Grovvy的知识点:

(1)可以省略 return 。这对不愿多打一个字母的懒人来说也是不小的福利;

(2)[]。这可不是数组,在Groovy中最常见的列表List;

(3)操作符重载:List 的 “ + ” 运算符。assert [1,2,3,4] == [1,2] + [3,4];

(4)*展开元素操作符。自动对List中的每个元素进行枚举操作,不用为此写一个for循环了;

(5)flatten() 。这是实现此算法的关键,它将所有递归得到的嵌套子节点List使用flatten操作,

得到一个一维的Group列表。List的这个flatten()方法能作到:

assert [1,2,3,4,5] == [1,[2,3],[[4]],[],5].flatten()

至此,一个完全可用的树状结构领域模型完成了,你可以调用Grails的GORM语法糖addToChildren,removeFromChildren 任意的添加/删除子节点,save,delete这些神奇的GORM方法自不用说,更不用写Hibernate的XML。

时间: 2024-10-13 15:59:35

神奇的Grails:自关联的树状Domain一行代码获取所有子节点的相关文章

HDU 1394 树状数组+离散化求逆序数

对于求逆序数问题,学会去利用树状数组进行转换求解方式,是很必要的. 一般来说我们求解逆序数,是在给定一串序列里,用循环的方式找到每一个数之前有多少个比它大的数,算法的时间复杂度为o(n2). 那么我们通过树状数组可以明显提高时间效率. 我们可以按照排列的顺序依次将数字放入树状数组中,并依次更新预与之相关联的树状数组元素.那么在将其更新完毕后,我们知道每个数对应的树状数组元素的左边的数肯定比它小,我们在以序列顺序依次更新树状数组时,如果有值在它前面出现,那么它对应的树状数组元素(在这个题目里存放的

bzoj 4871: [Shoi2017]摧毁“树状图”

4871: [Shoi2017]摧毁“树状图” Time Limit: 25 Sec  Memory Limit: 512 MBSubmit: 53  Solved: 9[Submit][Status][Discuss] Description 自从上次神刀手帮助蚯蚓国增添了上千万人口(蚯口?),蚯蚓国发展得越来越繁荣了!最近,他们在地下发现了 一些神奇的纸张,经过仔细研究,居然是D国X市的超级计算机设计图纸!这台计算机叫做‘树状图’,由n个计算 节点与n1条可以双向通信的网线连接而成,所有计算

树状数组总结——转

转自:夏天的风 http://blog.csdn.net/shahdza/article/details/6314818#comments 又做了几道树状数组的题,决定放一块儿总结一下:恩,总结一下.. (ps:大牛可以直接跳过...) 这得从一张图说起: 树状数组中用的d[],每个点都有一定的管辖范围: 如d[1]=a[1]; d[2]=a[1]+a[2]; d[3]=a[3]; d[4]=a[1]+a[2]+a[3]+a[4]; 等等: 这样的结构关键是为了,对一个数组内部动态的删除,增加,

树状数组知识点详解

树状数组 树状数组是一种数据结构,它的作用就是优化查询和修改的操作.试想,我们假如在做一道题的时候使用裸的一维数组来存储数据,那每次区间修改需要O(1)的时间,但查询却需要O(n)的时间,针对于某些题目,数据量奇大无比,必然会TLE.所以我们使用树状数组来优化这两个操作,使得修改和查询均可以在O(logn)的时间内完成,提升效率. (这是百度百科上树状数组的图) 可以直观地看出树状数组是个什么模式,是的,这就是一棵树,而这棵树上每个节点存储的数据就是它所有儿子节点的数据和.所以我们就可以在树上做

树状数组

树状数组                   转自:      By 岩之痕  http://blog.csdn.net/zearot/article/details/45028723 一.概述 树状数组是一种 用数组进行存储的 自下而上进行操作的  多叉树. 以下叙述中,A为原数组,C为树状数组所用的数组,B为特殊情况需要用到的辅助数组. 最基本的应用就是维护一个支持两种操作的数列:1.让A[i]加上某数X     2.求一个区间A[L] + A[L+1] + ... + A[R] 的和. 树

POJ 2352Stars 树状数组

Stars Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 42898   Accepted: 18664 Description Astronomers often examine star maps where stars are represented by points on a plane and each star has Cartesian coordinates. Let the level of a st

hdu-4417 Super Mario(树状数组 + 划分树)

题目链接: Super Mario Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 32768/32768 K (Java/Others) Problem Description Mario is world-famous plumber. His “burly” figure and amazing jumping ability reminded in our memory. Now the poor princess is

nyoj 322 Sort 【树状数组】

这道题其实就是考试树状数组. 代码: #include <cstdio> #include <cstring> int c[1005]; int lowbit(int x){ return x&(-x); } int getsum(int x){ int sum = 0; while(x){ sum += c[x]; x -= lowbit(x); } return sum; } void add(int x, int val){ while(x <= 1004){

hdu4605 Magic Ball Game(树状数组)

题目链接:点这里!!!! 题意: 给定一棵N(N<=1e5)节点的树,每个节点要么有两个儿子(左右两个儿子),要么没有儿子,每个节点有一个权值w[i]. 一个权值为X球从根节点开始下落,每落到一个节点的时候, 1.如果X=W[i],或者没有儿子节点了,球停止下落. 2.如果X<W[i],球各有1/2的概率落到左右儿子节点. 3.如果X>W[i],球有1/8的概率落到左儿子,有7/8的概率落到右儿子. 给你q(q<=1e5)个询问,询问中包含v,x.问你权值为x的球从根节点(根节点是