开发者

replacing 'eval' with a better solution

This method works, but it works very slowly. I think one of the problems might be the 'eval' statements in the add_by method.

Some explanation: every Node object has three relevant attributes, :x, :y and :neighbors. :x and :y are integers representing planar coordinates, :neighbors is an array, and nodes are stored in the @nodes array. The goal is to find, for each node k in @nodes, the nodes that are within some distance d of k and add them to the @neighbors array of 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

My question is, how would you do this without either repeating the add_by routine for x and y or using eval?


You can avoid eval by using @nodes[k].send dim.to_sym.

I'm not sure what your code is doing exactly, but maybe a few pointers:

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


How would I do it? I'd use the Neo4J graph database via the neo4j gem (source). If you're concerned about performance, this is optimized for graph distance calculations. Also the API is very nice.

That being said, you really don't need eval at all. You can call a calculated method name on an object by using send. So you can replace the above with @nodes[k].send(dim), @nodes[up].send(dim), etc.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜