2016-04-16 1 views
0

J'ai tableau javascript, où chaque élément a référence à parent, et ils peuvent être en boucle (référence circulaire). Exemple:Comment arrêter cette fonction récursive?

[ 
     {"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} 
] 

je avais besoin de créer une structure de données imbriqués en fonction enregistrement sélectionné pour l'afficher dans les DOM, que j'obtenus par fonction récursive comme ci-dessous (source 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 
} 

Il fonctionne très bien , mais pas pour les structures de données circulaires. La chose est que j'ai besoin d'arrêter l'exécution de la fonction avant qu'elle n'atteigne l'élément à partir duquel elle a démarré.

Comment puis-je y parvenir?

+0

Ajoutez un argument (tableau par exemple) qui conserve une liste des ID visités afin que vous puissiez les vérifier et les arrêter le cas échéant. – Cyb3rFly3r

+0

@ Cyb3rFly3r J'ai essayé mais j'ai obtenu des résultats bizarres ou incomplets. Pourriez-vous poster un exemple? Je place la condition au mauvais endroit. – Ketus

+0

On ne sait pas exactement quel est le résultat attendu puisque le code original produit toujours un tableau vide. – HeadCode

Répondre

1

Le tableau checked maintient les id s de tous les objets (parents) getNestedChildren était déjà mis à contribution.

Si le id de l'enfant actuel figure dans ce tableau, ne l'incluez pas en tant qu'enfant.

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

Malheureusement pour ID: 12 il ne produit qu'un seul enfant, ID 1 – Ketus

+0

Et combien attendiez-vous? Je ne vois qu'un seul enfant. – destoryer

+0

ID 12 a en effet un enfant ID1. ID1 a quatre enfants, ils ont des enfants et ainsi de suite jusqu'à ce que nous revenions à l'ID 12. – Ketus

1

Peut-être quelque chose comme cela devrait fonctionner pour vous:

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 je pensais que ça marcherait mais quand je commence à partir de l'ID 12, 4 niveaux de profondeur il y a aussi un objet avec ID 12. Des idées? – Ketus

1

Vous pouvez marquer les entrées que vous avez déjà visités. En fonction de cela, vous pouvez ignorer le traitement du même élément deux fois. Lorsque vous ajoutez la propriété children aux éléments, vous pouvez l'utiliser à cette fin, à condition de créer également cette propriété lorsqu'un élément n'a pas d'enfants.

code fonctionne ici faire:

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>')