Una API devuelve una estructura de datos anidados de matrices y objetos. Los datos vienen como una lista de objetos en forma de árbol, cada uno con una posible relación padre-hijo. La estructura en sí se muestra en el siguiente código de ejemplo.
[{ label: "search me", value: "searchme", children: [{ label: "search me too", value: "searchmetoo", children: [{ label: "No one can get me", value: "anonymous", }], }], }, { label: "search me2", value: "searchme2", children: [{ label: "search me too2", value: "searchmetoo2", children: [{ label: "No one can get me2", value: "anonymous2", }], }], }]Los datos anteriores deben convertirse en una matriz (plana) de objetos donde cada objeto representará un elemento de nodo anterior pero con una clave principal única (id). Además, el ID de padre de un nodo es igual al ID de su padre (la clave principal), excepto para los nodos raíz que no tienen padre y, por lo tanto, el ID de padre debe ser nulo.
La estructura de destino de los datos de origen proporcionados anteriormente coincide con el siguiente código...
[{ id: 1, // DIAGID parentId: null, // PARENTID label: "search me", // DIAGNOSIS value: "searchme" // DIAGTYPE }, { id: 2, parentId: 1, label: "search me too", value: "searchmetoo" }, { id: 3, parentId: 2, label: "No one can get me", value: "anonymous" }, { id: 4, parentId: null, label: "search me2", value: "searchme2" }, { id: 5, parentId: 4, label: "search me too2", value: "searchmetoo2" }, { id: 6, parentId: 5, label: "No one can get me2", value: "anonymous2" }]Puede tomar un método recursivo para Array#flatMap y almacenar el parent para la próxima llamada.
Este enfoque incrementa la id para todos los nodos.
const flatTree = (id => parent => ({ children = [], ...object }) => [ { id: ++id, ...object, parent }, ...children.flatMap(flatTree(id)) ])(0), tree = [{ label: 'search me', value: 'searchme', children: [{ label: 'search me too', value: 'searchmetoo', children: [{ label: 'No one can get me', value: 'anonymous' }] }] }, { label: 'four', searchme: '4four' }], flat = tree.flatMap(flatTree(null)); console.log(flat); .as-console-wrapper { max-height: 100% !important; top: 0; }Aquí hay una función recursiva dfs que realiza un recorrido de pedido previo a través del árbol de entrada y pasa a lo largo de un contador que alimenta la propiedad id que se usará en la salida. Además, la id del nodo actual se pasa como parentId a la llamada recursiva:
const dfs = (children, counter={id: 1}, parentId=null) => children.flatMap(({children=[], ...node}) => [{ ...counter, parentId, ...node }].concat(dfs(children, counter, counter.id++))); const response = [{label: "search me",value: "searchme",children: [{label: "search me too",value: "searchmetoo",children: [{label: "No one can get me",value: "anonymous",}],}],}, {label: "search me2",value: "searchme2",children: [{label: "search me too2",value: "searchmetoo2",children: [{label: "No one can get me2",value: "anonymous2",}],}],}]; const result = dfs(response); console.log(result);Iba a decir que todo lo que necesita es un recorrido de árbol recursivo, pero puede lograr lo mismo fácilmente con un generador:
function *visitNodes( root, parent = null, id = 0 ) { const node = { ...root, id : ++id, parentId = parent ? parent.id : null }; delete node.children; yield node; for ( const child of root.children ?? [] ) { yield *visitNodes(child, node, id); } }Habiendo definido el generador, puede iterar sobre los nodos:
for (const node of visitNodes( tree ) ) { // do something useful with node here }Puede convertirlo en una lista fácilmente, ya sea con el operador de propagación:
const nodes = [...visitNodes(tree)]; o usando Array.from() :
const nodes = Array.from( visitNodes(tree) );