Mam złożony plik json, który muszę obsługiwać za pomocą javascript, aby uczynić go hierarchicznym, aby później zbudować drzewo. Każda pozycja json ma: id: unikalny identyfikator, parentId: identyfikator węzła nadrzędnego (czyli 0, jeśli węzeł jest korzeniem drzewa) poziom: poziom głębokości w drzewie
Dane json są już „uporządkowane”. Chodzi mi o to, że wpis będzie miał nad sobą węzeł nadrzędny lub węzeł brata, a pod sobą węzeł podrzędny lub węzeł brat.
Wejście :
{
"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
},
]
}
Oczekiwany wynik :
{
"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
źródło
źródło
parentId
z0
oznacza, że nie ma identyfikatora rodzica i powinien być górną warstwą.Odpowiedzi:
Istnieje wydajne rozwiązanie, jeśli używasz wyszukiwania mapy. Jeśli rodzice zawsze przychodzą przed swoimi dziećmi, możesz połączyć obie pętle for. Obsługuje wiele korzeni. Daje błąd na wiszących gałęziach, ale można je zmodyfikować, aby je zignorować. Nie wymaga biblioteki innej firmy. To, o ile wiem, najszybsze rozwiązanie.
Jeśli interesujesz się teorią złożoności, to rozwiązanie to Θ (n log (n)). Rozwiązaniem z filtrem rekurencyjnym jest Θ (n ^ 2), co może stanowić problem w przypadku dużych zbiorów danych.
źródło
map
którym (w teorii) jest O (log n).Jak wspomniał @Sander, odpowiedź @ Halcyon zakłada wstępnie posortowaną tablicę, poniższe nie. (Zakłada się jednak, że załadowałeś underscore.js - chociaż można go zapisać w czystym javascript):
Kod
Wymagania
Zakłada, że właściwości „id” i „parentid” wskazują odpowiednio ID i ID rodzica. Muszą istnieć elementy z identyfikatorem rodzica 0, w przeciwnym razie otrzymasz z powrotem pustą tablicę. Osierocone elementy i ich potomkowie są „zagubieni”
http://jsfiddle.net/LkkwH/1/
źródło
else { parent['children'] = []; }
po pierwszej klauzuli if, aby upewnić się, że każdy węzeł ma atrybutchildren
(będzie pusty, jeśli węzeł jest węzłem liścia)tree
nigdy nie jest przekazywana jako argument przy rekurencyjnym wywołaniu funkcji, więc myślę, że wiersztree = typeof tree !== 'undefined' ? tree : [];
można zastąpić przezlet tree = [];
null
parent_ids zamiast 0? Edycja: Nevermind, mam to działa zmieniającid: 0
sięid: null
.(BONUS1: WĘZŁY MOGĄ LUB NIE MOGĄ BYĆ ZAMÓWIONE)
(BONUS2: NIE POTRZEBNA BIBLIOTEKA FIRM TRZECICH, ZWYKŁY JS)
(BONUS3: Użytkownik „Elias Rabl” twierdzi, że to najszybsze rozwiązanie, zobacz jego odpowiedź poniżej)
Oto ona:
Oto test, który może pomóc ci zrozumieć, jak działa rozwiązanie:
źródło
childNodes
tylko w razie potrzeby? Usuwając je z pierwszegoforEach
i przenosząc do drugiego?Miałem ten sam problem, ale nie byłem pewien, czy dane zostały posortowane, czy nie . Nie mogłem użyć biblioteki innej firmy, więc to jest po prostu wanilia Js; Dane wejściowe można zaczerpnąć z przykładu @ Stephena;
JS Fiddle
Płaska tablica do drzewa
źródło
mappedArr[mappedElem['parentid']]['children']
kończyło się niepowodzeniem, ponieważ nie można uzyskać dostępu dochildren
undefined.Użyj tego podejścia ES6. Działa jak urok
źródło
prostsza funkcja list-to-tree-lite
npm install list-to-tree-lite
listToTree(list)
źródło:
jsfiddle
źródło
Możesz poradzić sobie z tym pytaniem za pomocą tylko dwóch kodów kreskowych:
Testuj online (zobacz konsolę przeglądarki dla utworzonego drzewa)
Wymagania:
1- Zainstaluj lodash 4 (bibliotekę Javascript do manipulowania obiektami i kolekcjami metodami wydajnymi => jak Linq w c #) Lodash
2- Płaska tablica jak poniżej:
Dziękuję panu Bakhshabadi
Powodzenia
źródło
Przydatna może być instalacja listy pakietów w drzewie :
lub
Na przykład miej listę:
Użyj listy pakietów do drzewa:
Wynik:
źródło
Napisałem skrypt testowy do oceny wydajności dwóch najbardziej ogólnych rozwiązań (co oznacza, że dane wejściowe nie muszą być wcześniej sortowane i że kod nie zależy od bibliotek stron trzecich), zaproponowane przez użytkowników shekhardtu ( patrz odpowiedź ) i FurkanO ( patrz odpowiedź ).
http://playcode.io/316025?tabs=console&script.js&output
Rozwiązanie FurkanO wydaje się najszybsze.
źródło
To jest propozycja dla pozycji niezamówionych. Ta funkcja działa z pojedynczą pętlą i tabelą skrótów i zbiera wszystkie elementy z ich
id
. Jeśli zostanie znaleziony węzeł główny, obiekt jest dodawany do tablicy wyników.źródło
zrób to również z lodashjs (v4.x)
źródło
Podoba mi się czyste rozwiązanie JavaScript @ WilliamLeung, ale czasami trzeba wprowadzić zmiany w istniejącej tablicy, aby zachować odniesienie do obiektu.
Przykład: https://jsfiddle.net/kqw1qsf0/17/
źródło
źródło
Możesz rzucić okiem na drzewo pakietów npm Może być również bardzo przydatne, jeśli chcesz załadować dane z tabeli danych SQL DB. Możesz także łatwo dodać dodatkowe dane do węzłów w utworzonym drzewie.
Zastrzeżenie, zrobiłem ten pakiet.
źródło
Miałem podobny problem kilka dni temu, kiedy musiałem wyświetlić drzewo folderów z płaskiej tablicy. Nie widziałem tutaj żadnego rozwiązania w TypeScript, więc mam nadzieję, że będzie pomocny.
W moich przypadkach głównym rodzicem był tylko jeden, również tablica rawData nie musi być sortowana. Rozwiązania opierają się na przygotowaniu obiektu temp
{parentId: [child1, child2, ...] }
przykład surowych danych
def folderu
ROZWIĄZANIE : Funkcja zwracająca strukturę drzewa dla argumentu płaskiego
źródło
Oto prosta funkcja pomocnicza, którą stworzyłem na podstawie powyższych odpowiedzi, dostosowana do środowiska Babel:
źródło
Oto zmodyfikowana wersja Stevena Harrisa, która jest zwykłym ES5 i zwraca obiekt z kluczem id, zamiast zwracać tablicę węzłów zarówno na najwyższym poziomie, jak i dla dzieci.
źródło
To jest zmodyfikowana wersja powyższego, która działa z wieloma elementami głównymi, używam identyfikatorów GUID dla moich identyfikatorów i nadrzędnych, więc w interfejsie użytkownika, który je tworzy, koduję elementy główne na coś takiego jak 0000000-00000-00000-TREE-ROOT-ITEM
var drzewo = unflatten (rekordy, "ELEMENT-KORZENNY-DRZEWA");
źródło
Skopiowano z Internetu http://jsfiddle.net/stywell/k9x2a3g6/
źródło
Możesz użyć pakietu npm array-to-tree https://github.com/alferov/array-to-tree . Konwertuje zwykłą tablicę węzłów (ze wskaźnikami do węzłów nadrzędnych) na zagnieżdżoną strukturę danych.
Rozwiązuje problem z konwersją pobranych z bazy danych zestawów danych do zagnieżdżonej struktury danych (tj. Drzewa nawigacyjnego).
Stosowanie:
źródło
to jest to, czego użyłem w projekcie React
stosowanie:
wynik:
źródło
Możesz użyć tego pakietu "treeify" z Github tutaj lub z NPM .
Instalacja:
$ npm install --save-dev treeify-js
źródło
Moje rozwiązanie maszynopisowe, może ci pomoże:
Przykład użycia:
źródło
Napisałem wersję ES6 na podstawie odpowiedzi @Halcyon
Zasada tego algorytmu polega na użyciu „mapy” do ustalenia relacji indeksu. Łatwo jest znaleźć „element” na liście za pomocą „parentId” i dodać „dzieci” do każdego „elementu”, ponieważ „lista” jest relacją referencyjną, więc „korzenie” będą budować relacje z całym drzewem.
źródło
Odpowiedź na podobne pytanie:
https://stackoverflow.com/a/61575152/7388356
AKTUALIZACJA
Możesz użyć
Map
obiektu wprowadzonego w ES6. Zasadniczo zamiast znajdować rodziców przez ponowne iterowanie po tablicy, po prostu otrzymasz element nadrzędny z tablicy według identyfikatora rodzica, tak jak otrzymujesz elementy w tablicy według indeksu.Oto prosty przykład:
źródło
Opierając się na odpowiedzi @ FurkanO , stworzyłem kolejną wersję, która nie zmienia oryginalnych danych (jak zażądał @ Dac0d3r). Bardzo podobała mi się odpowiedź @ shekhardtu , ale zdałem sobie sprawę, że musiała wielokrotnie filtrować dane. Pomyślałem, że rozwiązaniem może być użycie odpowiedzi FurkanO poprzez skopiowanie najpierw danych. Wypróbowałem moją wersję w jsperf i wyniki były niestety (bardzo) ponure ... Wygląda na to, że zaakceptowana odpowiedź jest naprawdę dobra! Moja wersja jest jednak dość konfigurowalna i bezpieczna, więc i tak się nią z wami dzielę; oto mój wkład:
Za pomocą parametru options można skonfigurować, która właściwość ma być używana jako identyfikator lub identyfikator nadrzędny. Możliwe jest również skonfigurowanie nazwy właściwości podrzędnej, jeśli ktoś chce
"childNodes": []
lub coś.OP mógłby po prostu użyć domyślnych opcji:
Jeśli identyfikator rodzic jest falsy (
null
,undefined
lub inne wartości falsy) lub obiekt nadrzędny nie istnieje, uważamy obiektu przeznaczonego do węzła głównego.źródło
Spróbuj tego
Przetestuj na Jsfiddle
źródło
Konwertuj tablicę węzłów na drzewo
Funkcja ES6 do konwersji tablicy węzłów (powiązanych przez identyfikator nadrzędny ) - do struktury drzewa:
Generuj listę HTML z drzewa węzłów
Mając nasze drzewo na miejscu, oto rekurencyjna funkcja do budowania elementów UL> LI:
Czas demonstracyjny
Oto przykład mający liniową tablicę węzłów i używający obu powyższych funkcji:
źródło
To stary wątek, ale doszedłem do wniosku, że aktualizacja nigdy nie boli, dzięki ES6 możesz:
mam nadzieję, że to komuś pomoże
źródło