Tengo una estructura de datos de árbol con cada objeto que contiene niños:
const data = { id: 1, name: "John", parent_id: null, children: [{ id: 2, name: "Tess", parent_id: 1, children: [] }, { id: 3, name: "Tom", parent_id: 1, children: [{ id: 4, name: "Harry", parent_id: 3, children: [{ id: 7, name: "Thabo", parent_id: 4, children: [] }] }, { id: 5, name: "Mary", parent_id: 3, children: [] }, { id: 6, name: "Madge", parent_id: 3, children: [] } ] } ] } Antes de que pueda agregar un nuevo objeto al árbol, necesito determinar el valor de id más alto que se usa actualmente, para poder asignar el siguiente número disponible como id para el nuevo usuario.
Para hacer esto, creé una nueva variable con un valor inicial de 0. Luego itero sobre cada objeto en el árbol, y si la id del objeto es más alta que la nueva identificación, le asigno a la nueva identificación el valor de la identificación actual (la idea es tomando el valor final y sumando 1 para obtener el nuevo id).
let newUserID = 0; const newID = ( root, idKey ) => { if ( root.id > idKey ) { idKey = root.id; } root.children.forEach( ( obj ) => { newID( obj, idKey ); }); return idKey; } newUserID = newID( data, newUserID ); console.log( newUserID ); Esperaba que esto devolviera la id más alta en el árbol como el valor final, pero lo que realmente sucede es que, mientras que la nueva identificación aumenta hasta que coincide con el valor máximo, luego comienza a disminuir nuevamente y termina en 1.
Esto se puede ver en este JSFiddle que incluye algunos registros para mostrar el valor de la nueva ID en diferentes puntos de la función.
Desde entonces, resolví el problema usando un enfoque diferente (extrayendo los valores de id a una nueva matriz y usando Math.max() para encontrar el valor más alto), pero me gustaría entender por qué mi enfoque inicial no funcionó. como se esperaba. Puedo ver que el valor de idKey se está actualizando, pero luego el valor anterior se devuelve en la llamada recursiva, pero no sé por qué sucede eso o cómo evitarlo.
Simplemente asigne el valor devuelto de la llamada recursiva a idKey :
let newUserID = 0; const newID = ( root, idKey ) => { if ( root.id > idKey ) { idKey = root.id; } root.children.forEach( ( obj ) => { idKey = newID( obj, idKey ); // <-------- }); return idKey; } newUserID = newID( data, newUserID ); console.log( newUserID ); Sin esta asignación, no importa cuánto recurra, el valor devuelto dependerá solo del resultado de la instrucción if en la parte superior. Esto explica los registros que estaba recibiendo.
Primero, en cuanto a por qué su código está roto: acaba de perder una tarea. donde tienes
newID( obj, idKey ); está ignorando el valor resultante. Debe volver a asignarlo a idKey :
idKey = newID( obj, idKey ); Eso resolverá su problema. También debemos tener en cuenta que el nombre de la variable newUserID es un nombre un poco inapropiado, ya que no es el nuevo que usará sino el más alto encontrado. ¿Quizás highestUserID de usuario más alto sería menos confuso?
Sin embargo, debemos señalar que esto se puede escribir de manera mucho más simple, usando Math .max para hacer el trabajo pesado y una porción de recursividad. Así es como podría escribir esto:
const maxId = ({id, children = []}) => Math .max (id, ... children .map (maxId)) const data = {id: 1, name: "John", parent_id: null, children: [{id: 2, name: "Tess", parent_id: 1, children: []}, {id: 3, name: "Tom", parent_id: 1, children: [{id: 4, name: "Harry", parent_id: 3, children: [{id: 7, name: "Thabo", parent_id: 4, children: []}]}, {id: 5, name: "Mary", parent_id: 3, children: []}, {id: 6, name: "Madge", parent_id: 3, children: []}]}]} console .log (maxId (data))Puedes usar la recursividad para resolver esto. Como abajo
const data = { id: 1, name: "John", parent_id: null, children: [ { id: 2, name: "Tess", parent_id: 1, children: [], }, { id: 3, name: "Tom", parent_id: 1, children: [ { id: 4, name: "Harry", parent_id: 3, children: [ { id: 7, name: "Thabo", parent_id: 4, children: [], }, ], }, { id: 5, name: "Mary", parent_id: 3, children: [], }, { id: 6, name: "Madge", parent_id: 3, children: [], }, ], }, ], }; const findMax = (value) => { let max = -Infinity; const _findMax = (data) => { if (max < data.id) max = data.id; data.children.forEach(_findMax); }; _findMax(value); return max; }; console.log(findMax(data));