J'ai un fichier json complexe que je dois gérer avec javascript pour le rendre hiérarchique, afin de construire plus tard un arbre. Chaque entrée du json a: id: un identifiant unique, parentId: l'identifiant du nœud parent (qui vaut 0 si le nœud est une racine de l'arbre) level: le niveau de profondeur dans l'arbre
Les données json sont déjà «ordonnées». Je veux dire qu'une entrée aura au-dessus d'elle-même un nœud parent ou un nœud frère, et sous elle-même un nœud enfant ou un nœud frère.
Contribution :
{
"People": [
{
"id": "12",
"parentId": "0",
"text": "Man",
"level": "1",
"children": null
},
{
"id": "6",
"parentId": "12",
"text": "Boy",
"level": "2",
"children": null
},
{
"id": "7",
"parentId": "12",
"text": "Other",
"level": "2",
"children": null
},
{
"id": "9",
"parentId": "0",
"text": "Woman",
"level": "1",
"children": null
},
{
"id": "11",
"parentId": "9",
"text": "Girl",
"level": "2",
"children": null
}
],
"Animals": [
{
"id": "5",
"parentId": "0",
"text": "Dog",
"level": "1",
"children": null
},
{
"id": "8",
"parentId": "5",
"text": "Puppy",
"level": "2",
"children": null
},
{
"id": "10",
"parentId": "13",
"text": "Cat",
"level": "1",
"children": null
},
{
"id": "14",
"parentId": "13",
"text": "Kitten",
"level": "2",
"children": null
},
]
}
Production attendue :
{
"People": [
{
"id": "12",
"parentId": "0",
"text": "Man",
"level": "1",
"children": [
{
"id": "6",
"parentId": "12",
"text": "Boy",
"level": "2",
"children": null
},
{
"id": "7",
"parentId": "12",
"text": "Other",
"level": "2",
"children": null
}
]
},
{
"id": "9",
"parentId": "0",
"text": "Woman",
"level": "1",
"children":
{
"id": "11",
"parentId": "9",
"text": "Girl",
"level": "2",
"children": null
}
}
],
"Animals": [
{
"id": "5",
"parentId": "0",
"text": "Dog",
"level": "1",
"children":
{
"id": "8",
"parentId": "5",
"text": "Puppy",
"level": "2",
"children": null
}
},
{
"id": "10",
"parentId": "13",
"text": "Cat",
"level": "1",
"children":
{
"id": "14",
"parentId": "13",
"text": "Kitten",
"level": "2",
"children": null
}
}
]
}
javascript
arrays
list
tree
Franck
la source
la source
parentId
des0
signifie qu'il n'y a pas d'identifiant parent et devrait être la couche supérieure.Réponses:
Il existe une solution efficace si vous utilisez une recherche cartographique. Si les parents viennent toujours avant leurs enfants, vous pouvez fusionner les deux boucles pour. Il prend en charge plusieurs racines. Il donne une erreur sur les branches pendantes, mais peut être modifié pour les ignorer. Il ne nécessite pas de bibliothèque tierce. C'est, pour autant que je sache, la solution la plus rapide.
Si vous êtes dans la théorie de la complexité, cette solution est Θ (n log (n)). La solution du filtre récursif est Θ (n ^ 2), ce qui peut être un problème pour les grands ensembles de données.
la source
map
laquelle (en théorie) est O (log n).Comme mentionné par @Sander, la réponse de @ Halcyon suppose un tableau pré-trié, ce qui n'est pas le cas. (Cela suppose cependant que vous avez chargé le fichier underscore.js - bien qu'il puisse être écrit en javascript vanilla):
Code
Exigences
Il suppose que les propriétés «id» et «parentid» indiquent respectivement l'ID et l'ID parent. Il doit y avoir des éléments avec l'ID parent 0, sinon vous récupérez un tableau vide. Les éléments orphelins et leurs descendants sont `` perdus ''
http://jsfiddle.net/LkkwH/1/
la source
else { parent['children'] = []; }
après la première clause if pour vous assurer que chaque nœud a un attributchildren
(il sera vide si le nœud est un nœud feuille)tree
n'est jamais passé comme argument lors de l'appel de la fonction récursivement, donc je pense que la lignetree = typeof tree !== 'undefined' ? tree : [];
peut être remplacée parlet tree = [];
null
parent_ids au lieu de 0? Edit: Nevermind je l' ai eu de travail en changeant leid: 0
pourid: null
.(BONUS1: LES NOEUDS PEUVENT OU NE PAS ÊTRE COMMANDÉS)
(BONUS2: PAS DE BIBLIOTHÈQUE DE TROISIÈME PARTIE NÉCESSAIRE, PLAIN JS)
(BONUS3: l'utilisateur "Elias Rabl" dit que c'est la solution la plus rapide, voir sa réponse ci-dessous)
C'est ici:
Voici un test, il peut vous aider à comprendre comment fonctionne la solution:
la source
childNodes
uniquement en cas de besoin? En les supprimant du premierforEach
et en les déplaçant à l'intérieur du second?J'ai eu le même problème, mais je ne pouvais pas être certain que les données étaient triées ou non . Je ne pouvais pas utiliser une bibliothèque tierce donc ce n'est que vanilla Js; Les données d'entrée peuvent être tirées de l'exemple de @ Stephen;
JS Fiddle
Réseau plat à arbre
la source
mappedArr[mappedElem['parentid']]['children']
il échouait car l'accès àchildren
undefined.Utilisez cette approche ES6. Fonctionne comme du charme
la source
une fonction list-to-tree-lite plus simple
npm install list-to-tree-lite
listToTree(list)
la source:
jsfiddle
la source
Vous pouvez gérer cette question avec seulement deux codes de ligne:
Test en ligne (voir la console du navigateur pour l'arborescence créée)
Exigences:
1- Installer lodash 4 (une librairie Javascript pour manipuler des objets et des collections avec des méthodes performantes => comme le Linq en c #) Lodash
2- Un flatArray comme ci-dessous:
Merci M. Bakhshabadi
Bonne chance
la source
Il peut être utile d' installer une liste de paquets dans une arborescence :
ou
Par exemple, ayez la liste:
Utilisez la liste des paquets dans l'arborescence:
Résultat:
la source
J'ai écrit un script de test pour évaluer les performances des deux solutions les plus générales (ce qui signifie que l'entrée n'a pas à être triée au préalable et que le code ne dépend pas de bibliothèques tierces), proposé par les utilisateurs shekhardtu ( voir réponse ) et FurkanO ( voir la réponse ).
http://playcode.io/316025?tabs=console&script.js&output
La solution de FurkanO semble être la plus rapide.
la source
Ceci est une proposition pour les articles non commandés. Cette fonction fonctionne avec une seule boucle et avec une table de hachage et collecte tous les éléments avec leur
id
. Si un nœud racine est trouvé, l'objet est ajouté au tableau de résultats.la source
faites-le aussi avec lodashjs (v4.x)
la source
J'aime la solution JavaScript pure de @ WilliamLeung, mais parfois vous devez apporter des modifications au tableau existant pour conserver une référence à l'objet.
Exemple: https://jsfiddle.net/kqw1qsf0/17/
la source
la source
Vous pouvez jeter un œil au package npm tree-util. Il peut également être très pratique si vous souhaitez charger des données à partir d'une table de données SQL DB. Vous pouvez également facilement ajouter des données supplémentaires aux nœuds dans l'arborescence créée.
Avertissement, j'ai fait ce package.
la source
J'ai eu un problème similaire il y a quelques jours lorsque je dois afficher l'arborescence des dossiers à partir d'un tableau plat. Je n'ai vu aucune solution dans TypeScript ici, donc j'espère que cela vous sera utile.
Dans mon cas, le parent principal n'était qu'un seul, le tableau rawData n'a pas besoin d'être trié. Les solutions reposent sur la préparation d'un objet temporaire comme
{parentId: [child1, child2, ...] }
exemple de données brutes
def de dossier
SOLUTION : Fonction qui retourne l'arborescence pour l'argument plat
la source
Voici une fonction d'aide simple que j'ai créée sur le modèle des réponses ci-dessus, adaptée à un environnement Babel:
la source
Voici une version modifiée de Steven Harris qui est simple ES5 et renvoie un objet indexé sur l'id plutôt que de renvoyer un tableau de nœuds à la fois au niveau supérieur et pour les enfants.
la source
Ceci est une version modifiée de ce qui précède qui fonctionne avec plusieurs éléments racine, j'utilise des GUID pour mes identifiants et parentIds, donc dans l'interface utilisateur qui les crée, je code en dur les éléments racine en quelque chose comme 0000000-00000-00000-TREE-ROOT-ITEM
var tree = unflatten (enregistrements, "TREE-ROOT-ITEM");
la source
Copié sur Internet http://jsfiddle.net/stywell/k9x2a3g6/
la source
Vous pouvez utiliser le package array-to-tree de npm https://github.com/alferov/array-to-tree . Il convertit un tableau simple de nœuds (avec des pointeurs vers les nœuds parents) en une structure de données imbriquée.
Résout un problème de conversion d'ensembles de données extraits d'une base de données en une structure de données imbriquée (c.-à-d. Arbre de navigation).
Usage:
la source
c'est ce que j'ai utilisé dans un projet react
usage:
production:
la source
Vous pouvez utiliser ce package "treeify" de Github ici ou NPM .
Installation:
$ npm install --save-dev treeify-js
la source
Ma solution dactylographiée, peut-être qu'elle vous aide:
Exemple d'utilisation:
la source
J'ai écrit une version ES6 basée sur la réponse @Halcyon
Le principe de cet algorithme est d'utiliser "map" pour établir une relation d'index. Il est facile de trouver "item" dans la liste par "parentId", et d'ajouter "children" à chaque "item", car "list" est une relation de référence, donc "roots" construira des relations avec l'arborescence entière.
la source
Réponse à une question similaire:
https://stackoverflow.com/a/61575152/7388356
METTRE À JOUR
Vous pouvez utiliser un
Map
objet introduit dans ES6. Fondamentalement, au lieu de trouver les parents en itérant à nouveau sur le tableau, vous obtiendrez simplement l'élément parent du tableau par l'id du parent, comme vous obtenez les éléments d'un tableau par index.Voici l'exemple simple:
la source
Sur la base de la réponse de @ FurkanO , j'ai créé une autre version qui ne modifie pas les données d'origine (comme @ Dac0d3r demandé). J'ai vraiment aimé la réponse de @ shekhardtu , mais j'ai réalisé qu'elle devait filtrer les données plusieurs fois. J'ai pensé qu'une solution pourrait être d'utiliser la réponse de FurkanO en copiant d'abord les données. J'ai essayé ma version en jsperf , et les résultats étaient malheureusement (très) sombres ... Il semble que la réponse acceptée soit vraiment bonne! Ma version est tout à fait configurable et sécurisée, donc je la partage quand même avec vous; voici ma contribution:
Avec le paramètre options, il est possible de configurer la propriété à utiliser comme id ou id parent. Il est également possible de configurer le nom de la propriété children, si quelqu'un veut
"childNodes": []
ou quelque chose.OP pourrait simplement utiliser les options par défaut:
Si l'ID parent est faux (
null
,undefined
ou d' autres valeurs falsy) ou l'objet parent n'existe pas, nous considérons l'objet d'un nœud racine.la source
Essaye ça
Testez-le sur Jsfiddle
la source
Convertir les nœuds du tableau en arbre
Fonction ES6 pour convertir un tableau de nœuds (liés par l'ID parent ) - en une structure arborescente:
Générer une liste HTML à partir de l'arborescence des nœuds
Après avoir mis notre arbre en place, voici une fonction récursive pour construire les éléments UL> LI:
Temps de démonstration
Voici un exemple ayant un tableau linéaire de nœuds et utilisant les deux fonctions ci-dessus:
la source
C'est un vieux fil de discussion, mais je me suis dit qu'une mise à jour ne faisait jamais de mal, avec ES6, vous pouvez faire:
j'espère que ça aide quelqu'un
la source