Tengo un montón de objetos en una estructura plana. Estos objetos tienen una ID
y una ParentID
propiedad para que puedan organizarse en árboles. No están en un orden particular. Cada ParentID
propiedad no necesariamente coincide con un ID
en la estructura. Por lo tanto, podrían ser varios árboles que emergen de estos objetos.
¿Cómo procesarías estos objetos para crear los árboles resultantes?
No estoy tan lejos de una solución, pero estoy seguro de que está lejos de ser óptima ...
Necesito crear estos árboles para luego insertar datos en una base de datos, en el orden correcto.
No hay referencias circulares. Un nodo es un nodo raíz cuando ParentID == nulo o cuando ParentID no se puede encontrar en los otros objetos
algorithm
tree
language-agnostic
Costo
fuente
fuente
Respuestas:
Almacenar ID de los objetos en una tabla hash que se asigna al objeto específico. Enumere todos los objetos y encuentre su padre si existe y actualice su puntero padre en consecuencia.
fuente
Basado en la respuesta de Mehrdad Afshari y el comentario de Andrew Hanlon para una aceleración, aquí está mi opinión.
Diferencia importante con respecto a la tarea original: un nodo raíz tiene ID == parentID.
fuente
Aquí hay un algoritmo JavaScript simple para analizar una tabla plana en una estructura de árbol padre / hijo que se ejecuta en tiempo N:
fuente
console.log(JSON.stringify(root, null, 2));
para imprimir bastante la salida.Solución Python
Por ejemplo:
Produce:
fuente
def recurse(id, pages): for row in rows: if row['id'] == id: print(f'''{row['id']}:{row['parent_id']} {row['path']} {row['title']}''') recurse(row['id'], rows)
Versión JS que devuelve una raíz o una matriz de raíces, cada una de las cuales tendrá una propiedad de matriz Children que contiene los hijos relacionados. No depende de la entrada ordenada, decentemente compacta y no utiliza recursividad. ¡Disfrutar!
fuente
Encontré una increíble versión de JavaScript aquí: http://oskarhane.com/create-a-nested-array-recursively-in-javascript/
Digamos que tiene una matriz como esta:
Y quieres tener los objetos anidados así:
Aquí hay una función recursiva que lo hace posible.
Usuage:
fuente
Para cualquier persona interesada en una versión C # de la solución de Eugene, tenga en cuenta que se accede a node_list como un mapa, así que use un Diccionario en su lugar.
Tenga en cuenta que esta solución solo funciona si la tabla está ordenada por parent_id .
El nodo se define de la siguiente manera.
fuente
new Node { parent_id = 7, id = 9 },
impide quenode_list.Add(item.id, item);
se complete debido llave no se puede repetir; es un error tipográfico; entonces, en lugar de id = 9 , escriba id = 8Escribí una solución genérica en C # libremente basada en la respuesta de @Mehrdad Afshari:
fuente
Aquí está la solución Java de la respuesta de Mehrdad Afshari.
fuente
Aunque la pregunta me parezca vaga, probablemente crearía un mapa desde la ID hasta el objeto real. En pseudo-java (no comprobé si funciona / compila), podría ser algo como:
Y para buscar a cada padre:
Al reutilizar
getRealObject(ID)
y hacer un mapa de un objeto a una colección de objetos (o sus ID), también obtienes un mapa padre-> hijos.fuente
Puedo hacer esto en 4 líneas de código y tiempo O (n log n), suponiendo que Dictionary sea algo así como un TreeMap.
EDITAR : Ok, y ahora leí que algunos ID de padres son falsos, así que olvídate de lo anterior y haz esto:
fuente
La mayoría de las respuestas asumen que está buscando hacer esto fuera de la base de datos. Si sus árboles son de naturaleza relativamente estática y solo necesita mapear de alguna manera los árboles en la base de datos, puede considerar el uso de representaciones de conjuntos anidados en el lado de la base de datos. Echa un vistazo a los libros de Joe Celko (o aquí para obtener una descripción general de Celko).
Si está vinculado a Oracle dbs de todos modos, consulte su CONNECT BY para obtener enfoques SQL directos.
Con cualquier enfoque, puede omitir completamente la asignación de los árboles antes de cargar los datos en la base de datos. Solo pensé que ofrecería esto como una alternativa, puede ser completamente inapropiado para sus necesidades específicas. ¿La parte del "orden correcto" de la pregunta original implica que necesita que el orden sea "correcto" en la base de datos por alguna razón? Esto podría empujarme a manejar los árboles allí también.
fuente
No es exactamente lo que buscaba el autor de la pregunta, pero tuve dificultades para comprender las respuestas ambiguas que se proporcionan aquí, y todavía creo que esta respuesta encaja en el título.
Mi respuesta es para mapear una estructura plana a un árbol directamente en el objeto donde todo lo que tienes es un
ParentID
en cada objeto.ParentID
esnull
o0
si es una raíz. Frente al autor de la pregunta, supongo que todosParentID
los puntos válidos apuntan a algo más en la lista:fuente
Aquí hay una implementación de ruby:
Se catalogará por nombre de atributo o el resultado de una llamada al método.
fuente
La respuesta aceptada me parece demasiado compleja, así que agrego una versión de Ruby y NodeJS.
Suponga que la lista de nodos planos tiene la siguiente estructura:
Las funciones que convertirán la estructura de lista plana anterior en un árbol se ven de la siguiente manera
para Ruby:
para NodeJS:
fuente
null
debe ser paraundefined
null == undefined => true
en NodeJSUna forma elegante de hacer esto es representar los elementos de la lista como una cadena que contiene una lista de padres separada por puntos, y finalmente un valor:
Al armar un árbol, terminarías con algo como:
Tengo una biblioteca de configuración que implementa esta configuración de anulación (árbol) a partir de argumentos de la línea de comandos (lista). El algoritmo para agregar un solo elemento a la lista a un árbol está aquí .
fuente
¿Estás atrapado usando solo esos atributos? De lo contrario, podría ser bueno crear una matriz de nodos secundarios, donde puede recorrer todos estos objetos una vez para construir tales atributos. A partir de ahí, seleccione el nodo con hijos pero sin padres y construya iterativamente su árbol de arriba hacia abajo.
fuente
versión java
fuente