2010-11-12 5 views
0

Cette méthode fonctionne, mais elle fonctionne très lentement. Je pense que l'un des problèmes pourrait être les déclarations 'eval' dans la méthode add_by.en remplaçant 'eval' par une meilleure solution

Quelques explications: chaque objet Node a trois attributs pertinents, :x, :y et :neighbors. :x et :y sont des entiers représentant des coordonnées planaires, :neighbors est un tableau et les noeuds sont stockés dans le tableau @nodes. Le but est de trouver, pour chaque nœud k dans @nodes, les nœuds qui se trouvent à une certaine distance d de k et de les ajouter au tableau @neighbors de k.

def set_neighbors d 
    def add_by dim, d 
     dict = {} 
     @nodes.each{|k| dict[k] = []} 
     @nodes.each_index do |k| 
     up = k+1 
     down = k-1 
     while up < @nodes.length and ((eval '@nodes[k].'+ dim) - (eval '@nodes[up].'+dim)).abs <= d 
      dict[@nodes[k]].push(@nodes[up]) 
      up += 1 
     end 
     while down >= 0 and ((eval '@nodes[k].'+ dim) - (eval '@nodes[down].'+dim)).abs <= d 
      dict[@nodes[k]].push(@nodes[down]) 
      down -= 1 
     end 
     end 
     return dict 
    end 
    @nodes.sort_by{|k| k.x} 
    exis = add_by('x', d) 
    whys = add_by('y', d) 
    @nodes.each do |k| 
     neighbors = exis[k]&whys[k] 
     k.neighbors = neighbors.select{|j| planar_distance(j,k) <= d} 
    end 
    end 

Ma question est, comment voulez-vous faire sans soit répéter la routine add_by pour x et y ou en utilisant eval?

Répondre

3

Vous pouvez éviter eval en utilisant @nodes[k].send dim.to_sym.

Je ne suis pas sûr de ce que votre code est en train de faire exactement, mais peut-être quelques conseils:

def set_neighbors d 
    @nodes.each do |node| 
    node.neighbors = @nodes.select do |n| 
     (node.x - n.x).abs <= d && 
     (node.x - n.x).abs <= d && 
     planar_distance(n,node) <= d 
    end - node 
    end 
end 
+0

Cela a accéléré les choses un peu, merci! – philosodad

+0

Je devrais mentionner, cependant, que la raison de ne pas utiliser .select ici est parce que le nombre de noeuds est très, très grand, et les nombres qui sont dans la distance planaire sont petits. Donc, compter à partir de l'index après le tri a du sens ... il devrait y avoir un tri par là aussi. – philosodad

+0

Le code que vous avez fourni ne fait pas le tri. 'sort_by' ne fait pas de tri en place mais retourne plutôt un tableau trié. –

2

Comment qualifieriez-je le faire? J'utiliserais la base de données graphique Neo4J via le gem neo4j (source). Si vous êtes préoccupé par les performances, cela est optimisé pour les calculs de distance graphique. De plus, l'API est très belle.

Cela étant dit, vous n'avez vraiment pas besoin d'évaluation. Vous pouvez appeler un nom de méthode calculé sur un objet en utilisant send. Donc, vous pouvez remplacer le dessus avec @nodes[k].send(dim), @nodes[up].send(dim), etc

+0

Je vais vérifier cette gemme, merci. – philosodad

Questions connexes