Parent-Child 层级展开
大佬们,下午好😄 😄
我有这么一个问题,恳请大佬们有空的时候看看有没有更加简洁高效的实现方式。如下所示,要把左边的两列数据转换成右边的形式。左侧数据源中 1/1 是 1 的 Child,1/1/1 是 1/1 的 Child…以此类推。
为了方便测试,数据源如下所示,可以复制使用:
1 1/1
1 1/2
1 1/3
1/1 1/1/1
1/1 1/1/2
1/1/1 1/1/1/1
2 2/1
2 2/2
2 2/3
2/1 2/1/1
2/1 2/1/2
2/1/2 2/1/2/1
2/1/2 2/1/2/2
2/1/2 2/1/2/3
2/2 2/2/1
2/2 2/2/2
我写的 spl 语句如下:
=spl("=(x=?).select(!x.(~(2)).contain(~(1))).id(~(1)).([~])
=99.iterate((i=~,~~.news([P=~].insert(0,s=x.select(~(1)==P.m(i)));(x.delete(s),if(#>1,P.(null).insert(0,~.m(2)),P))).(#1)),A1,x==[])
",B2:C17)
简单解释一下:上述语句中 x 代表数据源,首先选出第一列 (父级) 中不存在于第二列 (子级) 中的值,也就是先确定最顶级的值[[1],[2]],然后再从数据源 x 的第一列中选出等于当前子级的数据后做笛卡尔积展开,同时从数据源中删除掉选出的值,进入下一轮迭代,直到数据源删完变成空后,迭代停止。很常规的思路,更谈不上算法,所以效率很一般,特别是 select 时的全表遍历复杂度应该很高,虽然每一次的遍历量都在减少,但感觉对整体的时间复杂度助力不大。spl 中有相关的 prior 和 nodes 函数,但这两个函数的运用我一直没吃透,运用起来有点费劲。所以不得已用 iterate 按条件迭代 99 次,这样不烧脑。
还有一种方法是深度优先遍历,用递归回溯,不知道会不会快一些:
A | B | C | D | |
1 | 1 1/1 1 1/2 1 1/3 1/1 1/1/1 1/1 1/1/2 1/1/1 1/1/1/1 2 2/1 2 2/2 2 2/3 2/1 2/1/1 2/1 2/1/2 2/1/2 2/1/2/1 2/1/2 2/1/2/2 2/1/2 2/1/2/3 2/2 2/2/1 2/2 2/2/2 | |||
2 | =A1.import@fw() | =A2.select(isdigit(~(1))) | =B2.id(~(1)).conj() | C2 的值表示最顶级 ["1","2"] |
3 | func | B3 表示递归最终结果 | C3 表示递归临时路径 | |
4 | =A2.pselect@a(~(1)==A3) | B4 的值表示位置,用位置索引 | ||
5 | if B4==[] | >C3.insert(0,A3) | 找不到位置时把当前值插入临时路径 | |
6 | >B3.insert(0,[C3.m(:)]) | 此时要把临时路径插入结果集 | ||
7 | >C3.delete(-1) | 同时临时路径要弹出刚插入的值,回溯 | ||
8 | for B4 | >v=A2.m(B8)(2) | 下一个进入递归的值 | |
9 | >C3.insert(0,A3) | if 语句避免重复插入结果,因为结果结构特殊,所以递归时也要对结果集赋值 | ||
10 | if #B8==1 | >B3.insert(0,[C3.m(:)]) | ||
11 | >C3.run(~=null) | 如果不需要相同的为空可省略此步赋值为空 | ||
12 | >func(A3,v,B3,C3) | 递归 | ||
13 | >C3.delete(-1) | 临时路径弹出插入的值,回溯 | ||
14 | return B3 | |||
15 | =C2.conj(func(A3,~,[],[])) | |||
16 | =E@pb(A15).array().m(2:) | |||
17 | =E@pb(A16) |
越琢磨越复杂。恳请大佬们有兴趣有闲时出手指点一下,给予帮助,谢谢!
prior 和 nodes 适用的数据结构是 [id,parentID,….] 这个样子,如果某条记录没有父则 parentID 为空。
你这个数据更像 [id,subID,…],并且 id 并不是包含了所有的,叶子层的没包含。
SPL:递归查找记录引用
有关 prior 和 nodes 可以在论坛上搜索一下“递归查找”,有相关的文章
谢谢大佬,我再琢磨琢磨😂 prior 和 nodes 有点不好搞,源数据正常一点应该没问题。
碰到这种层级关系,还有 BOM,一个头两个大。
用回溯写了一下,不会知道会不会快一些,A1 就是帖子中的数据文本。源表只 pselect 一遍,后续用位置索引。
我写了一个算法,看看效果怎么样
握艹,这么简洁,😂 …无语了,大佬威武,666👍 👍 👍
谢谢大佬出手帮助。佩服👍
我的思维框住了,看到父子层级就想着迭代递归,思维跳不出框框。自己把自己累的够呛😂
要跟大佬学习,think out of the box.
感谢🙏