Display Different Levels in a CSV File Using Indents
Problem description & analysis
Below is the content of CSV file csv.csv:
ID,MenuName,ParentID,isHidden,LinkURL
1,Company,NULL,False,/company
2,About Us,1,False,/company/aboutus
3,Mission,1,False,/company/mission
4,Team,2,False,/company/aboutus/team
5,Client 2,10,False,/references/client2
6,Client 1,10,False,/references/client1
7,Client 4,10,True,/references/client4
8,Client 5,10,True,/references/client5
10,References,NULL,False,/references
The CSV file stores relationships of menus. ParentID is ID of the superior level. Now we are trying to output menu names to console according to the following rules:
1. Output menu names in the order of parent & child. Use an indent to represent the parent-child relationship;
2. Display a menu name or not according to the isHidden value;
3. Sort menus of same level MenuName. Below is the desired result:
.Company
....About Us
.......Team
....Mission
.References
....Client 1
....Client 2
Solutions
Method 1: Through recursion
We write the following script p1.dfx in esProc:
A |
B |
C |
|
1 |
=file("csv.csv").import@ct() |
||
2 |
=func(A3,A1.select(ParentID==null),1) |
||
3 |
func |
||
4 |
for A3 |
>if(B4.isHidden=="False",output(fill(".",B3*3-2)/B4.MenuName)) |
|
5 |
=A1.select(ParentID==B4.ID).sort(MenuName) |
||
6 |
>if(C5.len()>0,func(A3,C5,B3+1)) |
Explanation:
A1 Import the CSV file as a table sequence, and add a new column level whose initial values are an empty set.
A2 Call A3’s subprogram, during which parameters are root nodes and the level number.
A3 Define a subprogram.
B4 Loop through A3, which corresponds to the first parameter in the subprogram.
C4 If value of B4’s isHidden is False, output the result of B3*3-2, in which B3 is the current level number, to the console. The result is the number of dots, which will be followed by B4’s MenuName value.
C5 Get all records of the next level.
C6 If the number of records in C5 is greater than 0, call Ad3’s subprogram where parameters are C5 and the current level number+1.
Method 2: By traversal
We write the following script p1.dfx in esProc:
A |
|
1 |
=file("csv.csv").import@ct().derive([]:level) |
2 |
>A1.switch(ParentID,A1:ID) |
3 |
=A1.nodes@p(ParentID) |
4 |
>A3.run(~.run(if(level==[],level=ParentID.level|MenuName))) |
5 |
=A1.select(isHidden=="False").sort(level).(fill(".",level.len()*3-2)/MenuName) |
6 |
>output(A5.concat@n()) |
Explanation:
A1 Import the CSV file as a table sequence, and add a new column level whose initial values are an empty set.
A2 Perform a self-join through primary key ID and foreign key ParentID.
A3 Search for every record referenced by foreign key ParentID recursively and return every referencing path between the root node to the current node.
A4 Loop through A3’s sequence and then the current member (a table sequence), during which assign ParentID.level plus MenuName to level if level value is null.
A5 Get records from A1 where isHidden value is False, sort them by level, and join multiple dots with MenuName value into a string according the rules.
A6 Concatenate A5’s strings into a large string by break line and output the result to console.
See How to Call an SPL Script in Java to learn about the integration of an SPL script with a Java program.
SPL Official Website 👉 https://www.scudata.com
SPL Feedback and Help 👉 https://www.reddit.com/r/esProcSPL
SPL Learning Material 👉 https://c.scudata.com
SPL Source Code and Package 👉 https://github.com/SPLWare/esProc
Discord 👉 https://discord.gg/cFTcUNs7
Youtube 👉 https://www.youtube.com/@esProc_SPL