2016-04-16 14 views
0

Ich habe Javascript Array, wo jedes Element Verweis auf Eltern hat, und sie können geloopt werden (Zirkelverweis). Beispiel:Wie kann diese rekursive Funktion gestoppt werden?

[ 
     {"id": 1, "firstName": "Macko","parentId": 12}, 
     {"id": 2, "firstName": "Jess","parentId": 1}, 
     {"id": 3, "firstName": "Peter","parentId": 1}, 
     {"id": 4, "firstName": "Lisa", "parentId": 1}, 
     {"id": 5, "firstName": "Megan","parentId": 1}, 
     {"id": 6, "firstName": "John", "parentId": 4}, 
     {"id": 7, "firstName": "Joe", "parentId": 4}, 
     {"id": 8, "firstName": "Matthew","parentId": 2}, 
     {"id": 9, "firstName": "Peter","parentId": 2}, 
     {"id": 10, "firstName": "Dio","parentId": 5}, 
     {"id": 11, "firstName": "Hello","parentId": 5}, 
     {"id": 12, "firstName": "Ana", "parentId": 4} 
] 

I verschachtelte Datenstruktur auf ausgewählte Datensatz basierend schaffen benötigen es im DOM anzuzeigen, die ich durch rekursive Funktion wie unten erreicht (Quelle here)

function getNestedChildren(arr, parent) { 
    var out = [] 
    for(var i in arr) { 
    if(arr[i].parent == parent) { 
     var children = getNestedChildren(arr, arr[i].id) 

     if(children.length) { 
      arr[i].children = children 
     } 
     out.push(arr[i]) 
    } 
    } 
    return out 
} 

Es funktioniert wirklich gut , aber nicht für zirkuläre Datenstrukturen. Die Sache ist, dass ich die Funktionsausführung stoppen muss, bevor sie das Element erreicht, von dem sie gestartet wurde.

Wie kann ich das erreichen?

+0

fügen Sie ein Argument hinzu (z. B. Array), das eine Liste der besuchten IDs enthält, damit Sie es überprüfen und gegebenenfalls stoppen können. – Cyb3rFly3r

+0

@ Cyb3rFly3r Ich habe das versucht, aber seltsame oder unvollständige Ergebnisse erhalten. Könnten Sie ein Beispiel veröffentlichen? Ich stelle den Zustand wahrscheinlich an die falsche Stelle. – Ketus

+0

Es ist unklar, was Ihr beabsichtigtes Ergebnis ist, da der ursprüngliche Code immer ein leeres Array erzeugt. – HeadCode

Antwort

1

Die checked Array hält die id s aller Objekte (Eltern) getNestedChildren bereits aufgerufen wurde.

Wenn das id des aktuellen Kindes in diesem Array ist, schließen Sie es nicht als untergeordnetes Element ein.

var arr = [ 
    {"id": 1, "firstName": "Macko","parentId": 12}, 
    {"id": 2, "firstName": "Jess","parentId": 1}, 
    {"id": 3, "firstName": "Peter","parentId": 1}, 
    {"id": 4, "firstName": "Lisa", "parentId": 1}, 
    {"id": 5, "firstName": "Megan","parentId": 1}, 
    {"id": 6, "firstName": "John", "parentId": 4}, 
    {"id": 7, "firstName": "Joe", "parentId": 4}, 
    {"id": 8, "firstName": "Matthew","parentId": 2}, 
    {"id": 9, "firstName": "Peter","parentId": 2}, 
    {"id": 10, "firstName": "Dio","parentId": 5}, 
    {"id": 11, "firstName": "Hello","parentId": 5}, 
    {"id": 12, "firstName": "Ana", "parentId": 4} 
]; 

var getNestedChildren = function(arr, id, checked) { 

    var out = []; 
    for (var i = 0; i < arr.length; i++) { 
    if (arr[i].parentId === id && checked.indexOf(arr[i].id) === -1) { 
     checked.push(id); 
     var children = getNestedChildren(arr, arr[i].id, checked); 
     if (children.length) { 
     arr[i].children = children; 
     } 
     out.push(arr[i]); 
    } 
    } 
    return out; 

}; 

console.log(getNestedChildren(arr, 12, [])); 
+0

Leider für ID: 12 produziert es nur ein Kind, ID 1 – Ketus

+0

Und wie viele haben Sie erwartet? Ich sehe nur ein Kind. – destoryer

+0

ID 12 hat tatsächlich ein Kind ID1. ID1 hat vier Kinder, sie haben Kinder und so weiter, bis wir zu ID 12 zurückkommen. – Ketus

1

Vielleicht so etwas wie dies sollte für Sie arbeiten:

function getNestedChildren(arr, parent, visited_list) { 
    var out = [] 
    for(var i in arr) { 
    if(!(arr[i].id in visited_list) && (arr[i].parentId == parent)) { 

     visited_list[arr[i].id] = true; 
     var children = getNestedChildren(arr, arr[i].id, visited_list) 

     if(children.length) { 
      arr[i].children = children 
     } 
     out.push(arr[i]) 
    } 
    } 
    return out 
} 

nestedList = getNestedChildren(arr, 1, []) 
+0

hm ich dachte, es würde funktionieren, aber wenn ich von ID 12, 4 Ebenen tief beginnen, gibt es auch Objekt mit ID 12. Irgendwelche Ideen? – Ketus

1

Sie könnten die Einträge markieren, die Sie bereits besucht haben. Auf dieser Grundlage können Sie die Verarbeitung desselben Elements zweimal überspringen.

Wenn Sie den Elementen die children-Eigenschaft hinzufügen, können Sie diese für diesen Markierungszweck verwenden, sofern Sie diese Eigenschaft auch dann erstellen, wenn ein Element keine untergeordneten Elemente enthält.

Hier arbeitet Code dies zu tun:

function getNestedChildren(arr, parent) { 
 
    var out = []; 
 
    for(var i in arr) { 
 
    if(arr[i].parentId == parent) { 
 
     if (arr[i].children === undefined) { 
 
      arr[i].children = [] 
 
      var children = getNestedChildren(arr, arr[i].id) 
 
      arr[i].children = children 
 
     } 
 
     out.push(arr[i]) 
 
    } 
 
    } 
 
    return out 
 
} 
 

 
var arr = [ 
 
    {"id": 1, "firstName": "Macko","parentId": 12}, 
 
    {"id": 2, "firstName": "Jess","parentId": 1}, 
 
    {"id": 3, "firstName": "Peter","parentId": 1}, 
 
    {"id": 4, "firstName": "Lisa", "parentId": 1}, 
 
    {"id": 5, "firstName": "Megan","parentId": 1}, 
 
    {"id": 6, "firstName": "John", "parentId": 4}, 
 
    {"id": 7, "firstName": "Joe", "parentId": 4}, 
 
    {"id": 8, "firstName": "Matthew","parentId": 2}, 
 
    {"id": 9, "firstName": "Peter","parentId": 2}, 
 
    {"id": 10, "firstName": "Dio","parentId": 5}, 
 
    {"id": 11, "firstName": "Hello","parentId": 5}, 
 
    {"id": 12, "firstName": "Ana", "parentId": 4} 
 
] 
 

 
getNestedChildren(arr, 1) 
 

 
// Output the lengths of the children's arrays 
 
document.body.innerHTML = arr.map(function (item) { 
 
    return 'Item ' + item.id + ' has ' + item.children.length + ' children.' 
 
}).join('<br>')

Verwandte Themen