J'ai les données suivantes:
var data = [
{ index : 4, sort : 4, parent : 0 },
{ index : 2, sort : 7, parent : 0 },
{ index : 1, sort : 10, parent : 0 },
{ index : 5, sort : 13, parent : 1 },
{ index : 8, sort : 6, parent : 5 },
{ index : 7, sort : 2, parent : 8 },
{ index : 6, sort : 20, parent : 5 },
{ index : 3, sort : 15, parent : 1 },
];
4 Réponses :
Edit: Scarp this, ça ne marche pas.
C'est le meilleur que j'ai géré. Qui devrait le trier. Je ne l'ai pas encore testé. Je laisserai la meilleure réponse ouverte pour voir si quelqu'un peut l'améliorer. P>
Cet algorithme me donne le même résultat que le mien. Qui est différent de celui que vous demandez dans votre question.
Après de nombreuses tentatives, j'ai monté cela. Cela fonctionne, mais n'est pas très élégant. Pourrait également faire avec abstraction dans sa propre classe.
// Initial sort places items in the correct sort order.
data.sort(function(a, b) {
return a.sort - b.sort;
});
vat top_parent_id = 1; // The value of an items parent if it is a top level item.
var sorted = []; // Empty array to copy sorted elements into.
var skipped = true; // flag to indicate if any elements have been skipped.
var skip_count = 0; // Counter to prevent infinite loops.
// Loop until no elements have been skipped.
//This loops through each level of the tree until all nested branches have been added
while(skipped){
skipped = false;
skip_count++;
if(skip_count === 50){ // Maximum tree depth.
throw "Error in sorted data or tree depth too great.";
break;
}
// Loop through the data in reverse order; this preserves the branch sort order.
for (var i = data.length - 1; i >= 0; i--) {
var item = data[i];
// Skip if this element has already been processed.
if(item.done)
continue;
// If this is this a top level item, then insert and continue.
if(item.parent == top_parent_id){
sorted.splice(0, 0, item); // Insert at the start; last item is the top sort.
item.done = true;
continue;
}
// Loop the new array to try and find this items parent.
var found = false;
for (var j = 0; j < sorted.length; j++) {
if(item.parent === sorted[j].index){
sorted.splice(j + 1, 0, item);
found = true;
item.done = true;
break;
}
}
// If a place for an item has not been found then skip it for now so it can be tested again on the next iteration.
if(!found){
skipped = true;
}
}
}
data = sorted;
Ce n'est pas votre approche d'origine, mais vous pouvez construire un arbre réel de vos données, comme celui-ci:
{ index: 4, sort: 4, parent: 0}
{ index: 2, sort: 7, parent: 0}
{ index: 1, sort: 10, parent: 0}
{ index: 5, sort: 13, parent: 1}
{ index: 8, sort: 6, parent: 5}
{ index: 7, sort: 2, parent: 8}
{ index: 6, sort: 20, parent: 5}
{ index: 3, sort: 15, parent: 1}
Merci Tomalak, c'est un bon peu de javascript. Plus efficace que la mienne aussi. Aussi un excellent exemple de récursivité.
@Systemicplural: Merci. Voir aussi la fonctionnalité ajoutée il y a quelques minutes.
Merci encore. J'ai décidé de croire de référence. Votre réponse est environ 250 fois plus rapide que la mienne. Par curiosité, j'ai ensuite converti votre réponse à une fermeture singleton et a gagné 10% supplémentaires. Pas certain de pourquoi. Il ne peut que gérer un seul arbre car c'est un singleton, mais c'est bien pour mon étui d'utilisation.
Joli! Si vous pouviez poster ce code comme une réponse de votre choix, j'aimerais y jeter un coup d'œil.
Je l'ai posté ci-dessous. J'ai changé quelques noms de variable pour refléter les échantillons de données dans ce post. Espérons que cela ne soit rien brisé.
Pourquoi trier à la fin et utiliser une récursion pour cela. Serait-il pas préférable de trier une seule fois au début?
@Alexandre Je pense que ce serait mieux, oui. Je ne me suis pas arrivé quand j'ai écrit cette réponse.
Toute idée de la performance est cette approche? Des points de repère?
Faire des mesures de vous en avez besoin. Le bâtiment de l'arborescence est exécuté en temps linéaire ( O (n) code>), il ne s'agit que de deux gares d'itérations après tout. Le tri prend un peu de temps supplémentaire, ce qui n'est pas nécessaire si les données sont pré-triées. Donc...
Demande de Tomalak ci-dessus que je pose ma version de la réponse de Singleton de leur réponse. Ici, il est: peuplule l'arbre avec: p> récupération d'une matrice triée avec: p> var sorted = [];
Tree.walk(function(){
sorted.push(this.data);
}, true);
+1 pour partager votre solution. FYI arguments.callee code> est obsolète.
Merci pour la tête sur Arguments.callee