2017-07-24 1 views
0

J'ai un JSON structuré en arbre qui devrait être filtré et le résultat devrait conserver la structure arborescente.Comment filtrer efficacement l'arborescence en conservant sa structure existante?

var tree = [ 
    { 
    text: "Parent 1", 
    nodes: [ 
     { 
     text: "Child 1", 
     type: "Child", 
     nodes: [ 
      { 
      text: "Grandchild 1" 
      type: "Grandchild" 
      }, 
      { 
      text: "Grandchild 2" 
      type: "Grandchild" 
      } 
     ] 
     }, 
     { 
     text: "Child 2", 
     type: "Child" 
     } 
    ] 
    }, 
    { 
    text: "Parent 2", 
    type: "Parent" 
    }, 
    { 
    text: "Parent 3", 
    type: "Parent" 
    } 
]; 

Exemple:

1) Si la requête de recherche est parent 1

Résultat attendu:

[ 
    { 
    text: "Parent 1", 
    nodes: [ 
     { 
     text: "Child 1", 
     type: "Child", 
     nodes: [ 
      { 
      text: "Grandchild 1" 
      type: "Grandchild" 
      }, 
      { 
      text: "Grandchild 2" 
      type: "Grandchild" 
      } 
     ] 
     }, 
     { 
     text: "Child 2", 
     type: "Child" 
     } 
    ] 
    } 
] 

2) Si la requête de recherche est l'enfant 1

Résultat attendu:

[ 
    { 
    text: "Parent 1", 
    nodes: [ 
     { 
     text: "Child 1", 
     type: "Child", 
     nodes: [ 
      { 
      text: "Grandchild 1" 
      type: "Grandchild" 
      }, 
      { 
      text: "Grandchild 2" 
      type: "Grandchild" 
      } 
     ] 
     } 
    ] 
    } 
] 

3) Si la requête de recherche est Grandchild 2

Résultat attendu:

[ 
    { 
    text: "Parent 1", 
    nodes: [ 
     { 
     text: "Child 1", 
     type: "Child", 
     nodes: [ 
      { 
      text: "Grandchild 2" 
      type: "Grandchild" 
      } 
     ] 
     } 
    ] 
    } 
] 

Je dois conserver la structure de l'arbre en fonction du niveau de noeud (type ici). Jusqu'à présent, j'ai essayé de filtrer de manière récursive mais je n'ai pas pu recadrer les résultats. Mon JSON est assez grand et donc le remappage basé sur les types devrait se faire dans le filtre lui-même. Veuillez nous contacter.

Répondre

2

Vous pouvez utiliser une approche récursive imbriquée et filtrer l'arborescence, tout en respectant l'élément trouvé.

function filter(array, text) { 
 
    return array.filter(function iter(o) { 
 
     var temp; 
 
     if (o.text === text) { 
 
      return true; 
 
     } 
 
     if (!Array.isArray(o.nodes)) { 
 
      return false; 
 
     } 
 
     temp = o.nodes.filter(iter); 
 
     if (temp.length) { 
 
      o.nodes = temp; 
 
      return true; 
 
     } 
 
    }); 
 
} 
 

 
var tree = [{ text: "Parent 1", nodes: [{ text: "Child 1", type: "Child", nodes: [{ text: "Grandchild 1", type: "Grandchild" }, { text: "Grandchild 2", type: "Grandchild" }] }, { text: "Child 2", type: "Child" }] }, { text: "Parent 2", type: "Parent" }, { text: "Parent 3", type: "Parent" }]; 
 

 
console.log(filter(tree, 'Parent 1')); 
 
console.log(filter(tree, 'Child 1')); 
 
console.log(filter(tree, 'Grandchild 2'));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Cette solution mute le tableau original. Si vous devez conserver le tableau d'origine, vous pouvez insérer une partie stringify/parse pour une copie du tableau.

return JSON.parse(JSON.stringify(array)).filter(function iter(o) {