Home > other >  javascript : Create visible indentation by id - parentId relationship in flatList
javascript : Create visible indentation by id - parentId relationship in flatList

Time:09-22

I have a flatlist with hierarchy structure represented by ID parentID relationship like so:

[
      { id: "100", bezeichnung: "Node 1", parentId: null },
      { id: "101", bezeichnung: "Node 1 A", parentId: "100" },
      { id: "102", bezeichnung: "Node 1 B", parentId: "100" },
      { id: "200", bezeichnung: "Node 2", parentId: null },
      { id: "201", bezeichnung: "Node 2 A", parentId: "200" },
      { id: "202", bezeichnung: "Node 2 B", parentId: "200" },
      { id: "204", bezeichnung: "Node 2 BA", parentId: "202" },
      { id: "203", bezeichnung: "Node 3 A", parentId: "200" }
    ]

I like to translate this into something like this:

[
      { id: "100", bezeichnung: "Node 1", parentId: null, indent: 0 },
      { id: "101", bezeichnung: "Node 1 A", parentId: "100", indent: 1 },
      { id: "102", bezeichnung: "Node 1 B", parentId: "100", indent: 1 },
      { id: "200", bezeichnung: "Node 2", parentId: null, indent: 0 },
      { id: "201", bezeichnung: "Node 2 A", parentId: "200", indent: 1 },
      { id: "202", bezeichnung: "Node 2 B", parentId: "200", indent: 1 },
      { id: "204", bezeichnung: "Node 2 BA", parentId: "202", indent: 2 },
      { id: "203", bezeichnung: "Node 3 A", parentId: "200", indent: 1 }
    ]

note that the above shown Ids might be arbitrary uuids and not 0,100,200 etc.

CodePudding user response:

So what you have is a list of nodes of a tree. Tree traversal is often most intuitively done using recursion:

let input = [
    { id: "100", bezeichnung: "Node 1", parentId: null },
    { id: "101", bezeichnung: "Node 1 A", parentId: "100" },
    { id: "102", bezeichnung: "Node 1 B", parentId: "100" },
    { id: "200", bezeichnung: "Node 2", parentId: null },
    { id: "201", bezeichnung: "Node 2 A", parentId: "200" },
    { id: "202", bezeichnung: "Node 2 B", parentId: "200" },
    { id: "204", bezeichnung: "Node 2 BA", parentId: "202" },
    { id: "203", bezeichnung: "Node 3 A", parentId: "200" }
];

input.forEach(element => element.indent = recursive(element,0))

function recursive (element, i) {
    if (!element.parentId) return i;
    return recursive(input.find(parent => parent.id === element.parentId), i 1)
}

console.log(input)

CodePudding user response:

If you want a non-mutating version (after all, we're not barbarians, right?!), you could try something like this:

const depths = (nodes, parentId = null, depth = 0) => 
  nodes .filter (n => n.parentId === parentId) 
        .flatMap (({id}) => [[id, depth], ...depths (nodes, id, depth   1)])

const addIndents = (nodes, indents = Object .fromEntries (depths (nodes))) => 
  nodes .map (node => ({...node, indent: indents [node .id]}))

const nodes = [{id: "100", bezeichnung: "Node 1", parentId: null}, {id: "101", bezeichnung: "Node 1 A", parentId: "100"}, {id: "102", bezeichnung: "Node 1 B", parentId: "100"}, {id: "200", bezeichnung: "Node 2", parentId: null}, {id: "201", bezeichnung: "Node 2 A", parentId: "200"}, {id: "202", bezeichnung: "Node 2 B", parentId: "200"}, {id: "204", bezeichnung: "Node 2 BA", parentId: "202"}, {id: "203", bezeichnung: "Node 3 A", parentId: "200"}]

console .log ('new list: ', addIndents (nodes))
console .log ('unmodified original: ', nodes)
.as-console-wrapper {max-height: 100% !important; top: 0}

Here we first calculate depths, which looks something like this:

[["100", 0], ["101", 1], ["102", 1], ["200", 0], ["201", 1], ["202", 1], ["204", 2], ["203", 1]]

then use fromEntries to convert that into an Object like this:

{"100": 0, "101": 1, "102": 1, "200": 0, "201": 1, "202": 1, "203": 1, "204": 2}

Then we map over the input, creating new nodes by shallow-cloning the old ones and adding an indent property.


I would suggest that if you're storing that property in something like raw data, that it might better be called depth rather than indent. Even if you're currently only planning on using it for indentation, depth is more generic and might apply to many more situations.

  • Related