Il y a un wikipedia article sur traversal arbre qui montre les différentes alternatives à la solution récursive que vous utilisez. Il peut être difficile de les utiliser dans votre cas particulier, mais cela devrait être possible. Cependant, ma question est la suivante: y a-t-il une raison particulière pour laquelle vous voulez utiliser l'itération plutôt que la récursivité? Je ne pense pas que l'une des solutions itératives sera presque aussi propre. Vos arbres sont-ils si gros que vous manquez d'espace de pile (ils devraient être assez gros)? Sinon, je ne suis pas sûr qu'une solution itérative soit vraiment plus rapide.
Je vois un potentiel d'amélioration cependant, si vous voyez des problèmes de performance ... mais je ne sais pas rails, donc je ne suis pas sûr si elle est exacte:
Est-ce que la méthode de recherche, renvoie un nouveau tableau? Si oui, vous voulez probablement invoquer .collect! au lieu de .collect, car si find crée un tableau, vous créez simplement un tableau, puis vous le lancez dans l'appel de collection (qui crée également un tableau), ce qui ne va certainement pas être très efficace et peut vous ralentir beaucoup si vous avez un grand arbre là-bas.
Alors
{ node.name => node.products.find(:all).collect(&:name) }.to_json
pourrait devenir
{ node.name => node.products.find(:all).collect!(&:name) }.to_json
EDIT: En outre, il peut être plus efficace pour créer votre hachage de hachages, puis convertir le tout en JSON en 1 coup, plutôt que de le convertir en morceaux comme vous le faites.
Alors
class Node < ActiveRecord::Base
has_many :products
def json_hash
if children.size > 0
children.collect { |node| { node.name => node.json_hash }.to_json
else
{ node.name => node.products.find(:all).collect!(&:name) }.to_json
end
end
end
pourrait devenir
class Node < ActiveRecord::Base
has_many :products
def json_hash
to_hash.to_json
end
def to_hash
if children.size > 0
children.collect { |node| { node.name => node.to_hash }
else
{ node.name => node.products.find(:all).collect!(&:name) }
end
end
end
Que cela fonctionne et est plus efficace que je laisse comme un exercice pour vous ;-)
Bonne réponse, mais je cherchais plus d'un moyen de Ruby itératif ou fantaisie pour le faire. – hoyhoy