Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

290
Visualizações
JavaScript flat list to tree WITHOUT parent id?

This question builds on many similar ones like Construct hierarchy tree from flat list with parent field?

However the twist is that there is no parent id. e.g.

[
{id: 1, depth: 1, ...},
{id: 2, depth: 2, ...},
{id: 3, depth: 3, ...},
{id: 4, depth: 2, ...},

{id: 5, depth: 1, ...},
{id: 6, depth: 2, ...},
{id: 7, depth: 2, ...},

{id: 8, depth: 1, ...},
{id: 9, depth: 2, ...},


{id: 10, depth: 3, ...},
{id: 11, depth: 3, ...},
]

What is a performant way to construct the following tree? Note that the children always come after the parent i.e. one can see the tree from the depth value. For example, id 2 is a child of id 1 since its depth is 2 and id 1 has a depth of 1. id 3 is a child of id 2 since id 3 has a depth of 3. id 4 is a child of id 1 not id 3 because id 4 has a depth of 2 (a step up) from id 3's depth of 3

\\tree digram
1
  2
    3
  4
5
  6
  7
8
  9
    10
    11

Should have values like

[
{id:1, depth:1, children: [
  {id: 2, depth: 2, children: [...]},
  ...
]},
{id:5, depth:1, children: [...]},
{id:6, depth:1, children: [...]},
]
about 4 years ago · Juan Pablo Isaza
3 Respostas
Responde à pergunta

0

You can use an array for this that has an index for each depth. At every moment, it will represent a path from the (virtual) root to the current node. When dealing with a node, its parent will sit at index depth-1, where it can be inserted in that parent's children property, and the node itself will be placed at index depth:

function createForest(flatdata) {
    const path = [{ children: [] }];
    for (const obj of flatdata) {
        path[obj.depth - 1].children.push(path[obj.depth] = { ...obj, children: [] });
    }
    return path[0].children;
}

// demo
const flatdata = [{id: 1, depth: 1},{id: 2, depth: 2},{id: 3, depth: 3},{id: 4, depth: 2},{id: 5, depth: 1},{id: 6, depth: 2},{id: 7, depth: 2},{id: 8, depth: 1},{id: 9, depth: 2},{id: 10, depth: 3},{id: 11, depth: 3}];
const roots = createForest(flatdata);

console.log(roots);

Irregular depths

If the depth values do not correspond to the actual depth of the nodes, but leave gaps, then use a "dictionary" (a plain object) to record the mapping of the depth property values with which real depth they correspond with:

function createForest(flatdata) {
    const path = [{ children: [] }];
    const depthMap = { 0: 0 };
    for (const obj of flatdata) {
        path[(depthMap[obj.depth] ??= path.length) - 1].children.push(
            path[depthMap[obj.depth]] = { ...obj, children: []}
        );
    }
    return path[0].children;
}

// demo
const flatdata = [{id: 1, depth: 10},{id: 2, depth: 20},{id: 3, depth: 30},{id: 4, depth: 20},{id: 5, depth: 10},{id: 6, depth: 20},{id: 7, depth: 20},{id: 8, depth: 10},{id: 9, depth: 20},{id: 10, depth: 30},{id: 11, depth: 30}];
const roots = createForest(flatdata);

console.log(roots);

If however, the only irregularity is that the depth does not always start at 1, but sometimes at 2, it will be more efficient to prefix the input data with a dummy depth-one node, use the first function, and then remove the dummy "root" (with depth 1) from the result.

about 4 years ago · Juan Pablo Isaza Relatório

0

Go through the array and add each item to the tree as well as to a trail of breadcrumbs. Each next item either goes as a child to the last one or you backtrack through the breadcrumb trail to the correct depth where it needs to be inserted:

const peek = arr =>
  arr[arr.length-1];

function toTree(arr) {
  const tree = [];
  const trail = [];
  
  for (const item of arr) {
    while ((peek(trail)?.depth ?? 0) >= item.depth) {
      trail.pop();
    }
    const current = peek(trail)?.children ?? tree;
    const treeNode = {...item, children: []};
    current.push(treeNode);
    trail.push(treeNode);
  }
  
  return tree;
}


const array = [
  {id: 1, depth: 1, },
  {id: 2, depth: 2, },
  {id: 3, depth: 3, },
  {id: 4, depth: 2, },

  {id: 5, depth: 1, },
  {id: 6, depth: 2, },
  {id: 7, depth: 2, },

  {id: 8, depth: 1, },
  {id: 9, depth: 2, },

  {id: 10, depth: 3  },
  {id: 11, depth: 3  },  
]

console.log(toTree(array));

This solution clones each item, in order to add the .children property. If no cloning is necessary, item can be directly mutated.

about 4 years ago · Juan Pablo Isaza Relatório

0

You could take an array of the last inserted objects.

const
    data = [{ id: 1, depth: 1 }, { id: 2, depth: 2 }, { id: 3, depth: 3 }, { id: 4, depth: 2 }, { id: 5, depth: 1 }, { id: 6, depth: 2 }, { id: 7, depth: 2 }, { id: 8, depth: 1 }, { id: 9, depth: 2 }, { id: 10, depth: 3 }, { id: 11, depth: 3 }],
    result = data.reduce((r, { depth, ...o }) => {
        r[depth - 1].push({ ...o, children: r[depth] = [] });
        return r;
    }, [[]])[0];

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda