S-022 – Ordenación de Jerarquías en árbol

Otra solución que tenía en el ámbito del lenguaje de PHP era la ordenación de jerarquías tipo árbol.  Es muy habitual contar con esta organización en tareas de un Gantt, estructura de personal en una compañía, etc., por lo que requerimos de un algoritmo para obtener esa jerarquía a partir de datos planos donde sólo se dispone del registro «padre» para montar esa estructura de árbol.

Objetivo

Disponer de un algoritmo en JavaScript que facilite un estructura jerarquica partiendo de registros que identifican cuál es el registro «padre».

DEMO: https://fhumanes.com/my-jerarquia/

Los campos con fondo amarillo son calculados.

(1) .- Es el orden de los registros según su estructura y su fecha de inicio.
(2).- Identificador de orden. Es el orden, teniendo en cuenta el nivel de dependencia.
(3).- Es el nivel de profundidad de la estructura para ese registro.
(4).- Indica si es un nodo maestro, que tiene registros dependiente de él.

Solución Técnica

La codificación la he hecho con Copilot. He facilitado a este el código que disponía de PHP y le he solicitado que lo transforme a JavaScript para utilizarlo en Svelte5 y en cualquier Front-End que tenga como base JavaScript.

Las funciones que hacen todo el trabajo ha quedado en un único fichero llamado «jerarquia.js»:

export function buildHierarchy(tasks) {
    const byId = new Map();
    const root = [];

    tasks.forEach(t => {
        t.children = [];
        byId.set(t.task_id, t);
    });

    tasks.forEach(t => {
        const parent = t.parent; // ← CAMBIO IMPORTANTE
        if (parent && parent !== t.task_id && byId.has(parent)) {
            byId.get(parent).children.push(t);
        } else {
            root.push(t);
        }
    });

    return root;
}


export function flattenHierarchy(tree, out, level = 1, path = []) {
    tree.forEach((node, index) => {

        // Construimos el nuevo path
        const newPath = [...path, index + 1];

        // Clonamos el nodo completo
        const item = { ...node };

        // Eliminamos children del objeto final
        delete item.children;

        // Campos calculados
        item.Nivel = level;
        item.Maestro = node.children.length > 0 ? 1 : 0;

        // NUEVO: estructura_id tipo "1.2.1."
        // item.estructura_id = newPath.join(".") + ".";
        item.estructura_id = newPath.join(".");

        // Añadimos al array plano
        out.push(item);

        // Recorremos hijos
        if (node.children.length > 0) {
            flattenHierarchy(node.children, out, level + 1, newPath);
        }
    });
}

export function ordenarTareas(tasks) {
    // console.log('Tareas antes de ordenar:', tasks);

    // Ordenar por fecha de inicio
    tasks.sort((a, b) => new Date(a.task_start_date) - new Date(b.task_start_date));

    console.log('Tareas después de ordenar por fecha:', tasks);
    const tree = buildHierarchy(tasks);

    // console.log('Jerarquía construida:', tree);
    const flat = [];
    flattenHierarchy(tree, flat);

    // console.log('Tareas aplanadas:', flat);
    flat.forEach((t, i) => {
        t.Orden = i + 1;
    });

    return flat;
}

El programa llama a la función «ordenaTareas», pasando el objeto JSON de las tareas obtenidas (en esta prueba directamente, pero debería ser del programa Back-End).

Realiza los siguientes pasos:

  • Ordenación de las Tareas por la fecha de inicio de la tarea.
  • Obtención del árbol de dependencias entre todas las tareas. «buildHierarchy».
  • Obtención de la estructura plana de los registros ordenados y los 4 campos calculados. «flattenHierarchy», Esta es una función recursiva, es decir, desde ella misma se instancia otras veces.

Creo que ha quedado simple, corta, entendible y muy práctica.

Como siempre, te dejo los fuentes del proyecto para que lo instales en tu PC y hagas todas las prácticas que precises.

Ahora es muy fácil consultar a una IA para clarificar el funcionamiento de un algoritmo, no obstante, si consideras que aún te quedan dudas, puedes contactar conmigo a través de email.

Adjuntos

Archivo Tamaño de archivo Descargas
zip my-jerarquia 19 KB 0

Blog personal para facilitar soporte gratuito a usuarios de React y PHPRunner