Ich habe eine komplexe JSON-Datei, die ich mit Javascript verarbeiten muss, um sie hierarchisch zu gestalten und später einen Baum zu erstellen. Jeder Eintrag des json hat: id: eine eindeutige ID, parentId: die ID des übergeordneten Knotens (die 0 ist, wenn der Knoten eine Wurzel des Baums ist) Ebene: die Ebene der Tiefe im Baum
Die JSON-Daten sind bereits "bestellt". Ich meine, ein Eintrag hat über sich einen übergeordneten Knoten oder einen Bruderknoten und unter sich einen untergeordneten Knoten oder einen Bruderknoten.
Eingabe:
{
"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
},
]
}
Erwartete Ausgabe :
{
"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
quelle
quelle
parentId
of0
bedeutet, dass es keine übergeordnete ID gibt und die oberste Ebene sein sollte.Antworten:
Es gibt eine effiziente Lösung, wenn Sie eine Kartensuche verwenden. Wenn die Eltern immer vor ihren Kindern stehen, können Sie die beiden for-Schleifen zusammenführen. Es unterstützt mehrere Wurzeln. Es gibt einen Fehler bei baumelnden Zweigen, kann aber geändert werden, um sie zu ignorieren. Es ist keine Bibliothek eines Drittanbieters erforderlich. Soweit ich das beurteilen kann, ist es die schnellste Lösung.
Wenn Sie sich mit Komplexitätstheorie beschäftigen, lautet diese Lösung Θ (n log (n)). Die rekursive Filterlösung ist Θ (n ^ 2), was bei großen Datenmengen ein Problem sein kann.
quelle
map
der (theoretisch) O (log n) ist.Wie von @Sander erwähnt, geht die Antwort von @ Halcyon von einem vorsortierten Array aus, das Folgende nicht. (Es wird jedoch davon ausgegangen, dass Sie underscore.js geladen haben - obwohl es in Vanille-Javascript geschrieben sein könnte):
Code
Bedarf
Es wird davon ausgegangen, dass die Eigenschaften 'id' und 'parentid' die ID bzw. die übergeordnete ID angeben. Es müssen Elemente mit der übergeordneten ID 0 vorhanden sein, andernfalls erhalten Sie ein leeres Array zurück. Verwaiste Elemente und ihre Nachkommen sind "verloren"
http://jsfiddle.net/LkkwH/1/
quelle
else { parent['children'] = []; }
nach der ersten if-Klausel hinzufügen , um sicherzustellen, dass jeder Knoten ein Attribut hatchildren
(es wird leer sein, wenn der Knoten ein Blattknoten ist)tree
wird beim rekursiven Aufrufen der Funktion nie als Argument übergeben, daher denke ich, dass die Zeiletree = typeof tree !== 'undefined' ? tree : [];
durchlet tree = [];
null
Könnte dies geändert werden, um parent_ids anstelle von 0 zuzulassen ? Edit: Nevermind, ich habe es funktioniert durch die Veränderungid: 0
anid: null
.(BONUS1: NODES KÖNNEN ODER KÖNNEN NICHT BESTELLT WERDEN)
(BONUS2: KEINE BIBLIOTHEK VON DRITTANBIETERN BENÖTIGT, PLAIN JS)
(BONUS3: Benutzer "Elias Rabl" sagt, dies sei die schnellste Lösung, siehe seine Antwort unten)
Hier ist es:
Hier ist ein Test, der Ihnen helfen kann, die Funktionsweise der Lösung zu verstehen:
quelle
childNodes
nur bei Bedarf hinzufügen würden ? Indem Sie sie von der ersten entfernenforEach
und in die zweite verschieben?Hatte das gleiche Problem, aber ich konnte nicht sicher sein, ob die Daten sortiert waren oder nicht . Ich konnte keine Bibliothek von Drittanbietern verwenden, daher ist dies nur Vanilla Js. Die Eingabedaten können dem Beispiel von @ Stephen entnommen werden.
JS Fiddle
Flaches Array zum Baum
quelle
mappedArr[mappedElem['parentid']]['children']
fehl, da der Zugriff aufchildren
undefined nicht möglich ist.Verwenden Sie diesen ES6-Ansatz. Funktioniert wie Charme
quelle
eine einfachere Funktion list-to-tree-lite
npm install list-to-tree-lite
listToTree(list)
Quelle:
jsfiddle
quelle
Sie können diese Frage mit nur zwei Zeilen behandeln:
Online testen (siehe Browser-Konsole für erstellten Baum)
Bedarf:
1- Installieren Sie lodash 4 (eine Javascript-Bibliothek zum Bearbeiten von Objekten und Sammlungen mit performanten Methoden => wie die Linq in c #) Lodash
2- Ein flatArray wie unten:
Vielen Dank, Herr Bakhshabadi
Viel Glück
quelle
Es kann nützlich sein, die Paketliste in den Baum zu installieren:
oder
Zum Beispiel Liste haben:
Verwenden Sie die Paketliste zum Baum:
Ergebnis:
quelle
Ich habe ein Testskript geschrieben, um die Leistung der beiden allgemeinsten Lösungen zu bewerten (was bedeutet, dass die Eingabe nicht vorher sortiert werden muss und der Code nicht von Bibliotheken von Drittanbietern abhängt), das von den Benutzern shekhardtu vorgeschlagen wurde ( siehe Antwort ). und FurkanO ( siehe Antwort ).
http://playcode.io/316025?tabs=console&script.js&output
Die Lösung von FurkanO scheint die schnellste zu sein.
quelle
Dies ist ein Vorschlag für ungeordnete Artikel. Diese Funktion arbeitet mit einer einzelnen Schleife und einer Hash-Tabelle und sammelt alle Elemente mit ihren
id
. Wenn ein Stammknoten gefunden wird, wird das Objekt dem Ergebnisarray hinzugefügt.quelle
mach es auch mit lodashjs (v4.x)
quelle
Ich mag die reine JavaScript-Lösung von @ WilliamLeung, aber manchmal müssen Sie Änderungen am vorhandenen Array vornehmen, um einen Verweis auf das Objekt beizubehalten.
Beispiel: https://jsfiddle.net/kqw1qsf0/17/
quelle
quelle
Vielleicht sehen Sie sich das npm-Paket tree-util an Sie sich Es kann auch sehr praktisch sein, wenn Sie Daten aus einer SQL DB-Datentabelle laden möchten. Sie können den Knoten im erstellten Baum auch problemlos zusätzliche Daten hinzufügen.
Haftungsausschluss, ich habe dieses Paket gemacht.
quelle
Ich hatte vor ein paar Tagen ein ähnliches Problem, als ich einen Ordnerbaum aus einem flachen Array anzeigen musste. Ich habe hier keine Lösung in TypeScript gesehen, daher hoffe ich, dass sie hilfreich ist.
In meinen Fällen waren die Haupteltern nur eine, auch das rawData-Array muss nicht sortiert werden. Lösungen basieren auf der Vorbereitung von temporären Objekten wie
{parentId: [child1, child2, ...] }
Beispiel Rohdaten
def des Ordners
LÖSUNG : Funktion, die die Baumstruktur für ein flaches Argument zurückgibt
quelle
Hier ist eine einfache Hilfsfunktion, die ich nach dem Vorbild der obigen Antworten erstellt habe und die auf eine Babel-Umgebung zugeschnitten ist:
quelle
Hier ist eine modifizierte Version von Steven Harris ', die einfach ES5 ist und ein Objekt zurückgibt, das auf der ID verschlüsselt ist, anstatt ein Array von Knoten sowohl auf der obersten Ebene als auch für die Kinder zurückzugeben.
quelle
Dies ist eine modifizierte Version des oben genannten, die mit mehreren Stammelementen funktioniert. Ich verwende GUIDs für meine IDs und übergeordneten IDs. In der Benutzeroberfläche, die sie erstellt, codiere ich Stammelemente fest in etwas wie 0000000-00000-00000-TREE-ROOT-ITEM
var tree = unflatten (Datensätze, "TREE-ROOT-ITEM");
quelle
Aus dem Internet kopiert http://jsfiddle.net/stywell/k9x2a3g6/
quelle
Sie können das npm-Paket array-to-tree https://github.com/alferov/array-to-tree verwenden . Es konvertiert ein einfaches Array von Knoten (mit Zeigern auf übergeordnete Knoten) in eine verschachtelte Datenstruktur.
Behebt ein Problem bei der Konvertierung von aus einer Datenbank abgerufenen Datensätzen in eine verschachtelte Datenstruktur (dh einen Navigationsbaum).
Verwendung:
quelle
Das habe ich in einem Reaktionsprojekt verwendet
Verwendung:
Ausgabe:
quelle
Sie können dieses "treeify" -Paket von Github hier oder NPM verwenden .
Installation:
$ npm install --save-dev treeify-js
quelle
Meine Typoskript-Lösung hilft Ihnen vielleicht:
Anwendungsbeispiel:
quelle
Ich habe eine ES6-Version geschrieben, die auf der Antwort von @Halcyon basiert
Das Prinzip dieses Algorithmus besteht darin, "map" zu verwenden, um eine Indexbeziehung herzustellen. Es ist einfach, "Element" in der Liste mit "parentId" zu finden und jedem "Element" "Kinder" hinzuzufügen, da "Liste" eine Referenzbeziehung ist, sodass "Wurzeln" Beziehungen zum gesamten Baum aufbauen.
quelle
Antwort auf eine ähnliche Frage:
https://stackoverflow.com/a/61575152/7388356
AKTUALISIEREN
Sie können
Map
ein in ES6 eingeführtes Objekt verwenden. Anstatt Eltern zu finden, indem Sie das Array erneut durchlaufen, erhalten Sie das übergeordnete Element aus dem Array anhand der ID des Elternteils, so wie Sie Elemente in einem Array anhand des Index erhalten.Hier ist das einfache Beispiel:
quelle
Basierend auf der Antwort von @ FurkanO habe ich eine andere Version erstellt, die die ursprünglichen Daten nicht mutiert (wie @ Dac0d3r angefordert). Die Antwort von @ shekhardtu hat mir sehr gut gefallen , aber mir wurde klar, dass sie viele Male durch die Daten filtern musste. Ich dachte, eine Lösung könnte darin bestehen, die Antwort von FurkanO zu verwenden, indem zuerst die Daten kopiert werden. Ich habe meine Version in jsperf ausprobiert und die Ergebnisse waren leider (sehr) trostlos ... Es scheint, dass die akzeptierte Antwort wirklich gut ist! Meine Version ist ziemlich konfigurierbar und ausfallsicher, also teile ich sie trotzdem mit euch. Hier ist mein Beitrag:
Mit dem Parameter options kann konfiguriert werden, welche Eigenschaft als ID oder übergeordnete ID verwendet werden soll. Es ist auch möglich, den Namen der Eigenschaft child zu konfigurieren, wenn jemand möchte
"childNodes": []
oder etwas.OP könnte einfach Standardoptionen verwenden:
Wenn die übergeordnete ID falsy (ist
null
,undefined
oder andere falsy Werte) oder das übergeordnete Objekt existiert nicht, betrachten wir das Objekt ein Wurzelknoten sein.quelle
Versuche dies
Testen Sie es auf Jsfiddle
quelle
Konvertieren Sie das Knotenarray in einen Baum
ES6-Funktion zum Konvertieren eines Array von Knoten (bezogen auf die übergeordnete ID ) - in eine Baumstruktur:
Generieren Sie eine HTML-Liste aus dem Knotenbaum
Wenn unser Baum vorhanden ist, ist hier eine rekursive Funktion zum Erstellen der UL> LI-Elemente:
Demo-Zeit
Hier ist ein Beispiel mit einem linearen Array von Knoten und der Verwendung der beiden oben genannten Funktionen:
quelle
Dies ist ein alter Thread, aber ich dachte, ein Update tut nie weh. Mit ES6 können Sie Folgendes tun:
hoffe es hilft jemandem
quelle