2010-11-12 48 views
0

此方法可行,但工作起來非常緩慢。我認爲其中一個問題可能是add_by方法中的'eval'聲明。用更好的解決方案取代'eval'

一些解釋:每節點對象有三個相關屬性,:x:y:neighbors:x:y是代表平面座標的整數,:neighbors是一個數組,節點存儲在@nodes數組中。我們的目標是找到k中的每個節點k@nodes中的節點,這些節點位於k的某個距離d內,並將它們添加到k@neighbors數組中。

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 

我的問題是,你會怎麼做這個沒有任何重複add_by例程xy或使用eval?

回答

3

您可以通過使用@nodes[k].send dim.to_sym來避免評估。

我不知道你的代碼是做完全是,但也許幾個要點:

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

加快了這一點,謝謝! – philosodad 2010-11-12 14:10:47

+0

但是,我應該提到,不在這裏使用.select的原因是因爲節點的數量非常非常大,而且在平面距離內的數量很小。因此,在排序之後從索引中計數是有意義的......在那裏也應該有y排序。 – philosodad 2010-11-23 00:23:06

+0

您提供的代碼實際上沒有排序。 'sort_by'不會進行排序,而是返回一個有序數組。 – 2010-11-23 00:36:26

2

將如何辦呢?我會通過neo4j gem使用Neo4J圖形數據庫(source)。如果你關心性能,這是針對圖形距離計算進行優化的。此外,API非常好。

這就是說,你真的不需要eval。您可以使用send在對象上調用計算方法名稱。所以你可以用@nodes[k].send(dim)@nodes[up].send(dim)等替換上面的。

+0

我會檢查那寶石,謝謝。 – philosodad 2010-11-12 14:16:04

相關問題