заменив 'eval' на лучшее решение - PullRequest
0 голосов
/ 12 ноября 2010

Этот метод работает, но работает очень медленно.Я думаю, что одной из проблем могут быть операторы 'eval' в методе add_by.

Некоторое объяснение: каждый Узел объект имеет три соответствующих атрибута, :x, :y и :neighbors.:x и :y - целые числа, представляющие плоские координаты, :neighbors - массив, а узлы хранятся в массиве @nodes.Цель состоит в том, чтобы найти для каждого узла k в @nodes узлы, которые находятся на некотором расстоянии d от k, и добавить их в массив @neighbors из 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

Мой вопрос: как бы вы сделали это без повторения процедуры add_by для x и y или с использованием eval?

Ответы [ 2 ]

3 голосов
/ 12 ноября 2010

Вы можете избежать eval, используя @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
2 голосов
/ 12 ноября 2010

Как бы I сделал это?Я бы использовал графическую базу данных Neo4J через гем neo4j ( source ).Если вы беспокоитесь о производительности, это оптимизировано для расчета расстояния графика.Кроме того, API очень хороший.

При этом вам действительно не нужен eval.Вы можете вызвать вычисляемое имя метода для объекта, используя send.Таким образом, вы можете заменить вышеуказанное на @nodes[k].send(dim), @nodes[up].send(dim) и т. Д.

...