替换“评估”;有更好的解决方案

发布于 2024-10-02 06:56:44 字数 1319 浏览 0 评论 0原文

这个方法确实有效,但是效果非常慢。我认为问题之一可能是 add_by 方法中的“eval”语句。

一些解释:每个 Node 对象都有三个相关属性,:x:y:neighbors:x:y 是代表平面坐标的整数,:neighbors 是一个数组,节点存储在 @nodes< /代码> 数组。目标是为 @nodes 中的每个节点 k 找到距 kd 一定距离内的节点code> 并将它们添加到 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

我的问题是,如何在不重复 xyadd_by 例程或使用 eval 的情况下执行此操作?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

命比纸薄 2024-10-09 06:56:44

您可以使用 @nodes[k].send dim.to_sym 来避免 eval。

我不确定你的代码到底在做什么,但也许有一些提示:

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

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
笨死的猪 2024-10-09 06:56:44

会怎样做呢?我将通过 neo4j gem 使用 Neo4J 图形数据库 (来源)。如果您担心性能,这针对图形距离计算进行了优化。 API 也非常好。

话虽这么说,你真的根本不需要 eval。您可以使用 send 在对象上调用计算方法名称。所以你可以用@nodes[k].send(dim)@nodes[up].send(dim)等替换上面的内容。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文