编写“类似 Excel”的最佳方法Ruby 的影响力网络?

发布于 2024-11-17 10:52:44 字数 243 浏览 4 评论 0原文

我有一个节点网络,每个节点都会影响其他一些节点的状态(想象一个 Excel 电子表格,其单元格值通过公式取决于其他单元格)。

我想知道在 Ruby 中实现这个最干净的方法是什么?

当然,我可以每个节点有一个进程,但是如果节点数量增加,它将如何执行?而且,我确信有相关的库,但我找不到最新的库。

感谢您的帮助 !

更新:听起来 EventMachine 可以完成这项工作......但它似乎更适合少量的“节点”

I have a network of nodes, each node influencing the state of some other nodes (imagine an Excel spreadsheet with cells values depending on other cells through formulas).

I'm wondering what is the cleanest way to implement this in Ruby ?

Of course I could have one process per node, but how will it perform if the number of nodes increases ? And, I'm sure there are libraries for that, but I can't find a up-to-date one.

Thanks for your help !

Update: Sounds like EventMachine might do the job... but it seems more adapted to a small number of "nodes"

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

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

发布评论

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

评论(3

何止钟意 2024-11-24 10:52:44

对于观察者模式来说,这听起来是一个很好的情况。这是 ruby​​ 中的示例:

require 'observer'

class Node
  attr_accessor :id
  @@current_node_id = 0
  def initialize
    @@current_node_id += 1
    id = @@current_node_id
  end
  include Observable

  attr_reader :value


  protected
  def value=(new_value)
    return if @value == new_value
    old_value = @value
    @value = new_value
    changed
    notify_observers(id, old_value, @value)
  end
end


class ValueNode < Node
  def initialize(initial_value)
    super()
    @value = initial_value
  end

  def value=(new_value)
    super(new_value)
  end
end


class SumNode < Node
  def initialize(*nodes)
    super()
    @value = nodes.map(&:value).inject(0, &:+)
    nodes.each do |node|
      node.add_observer(self)
    end
  end


  def update(id, old_value, new_value)
    self.value = self.value - old_value + new_value
  end
end


def test
  v1 = ValueNode.new 4
  v2 = ValueNode.new 8
  sum = SumNode.new(v1, v2)
  sum2 = SumNode.new(v1, sum)
  v2.value = 10
  p sum.value
  p sum2.value
end


test()

请注意 SumNode 的值不会在每次请求时重新计算,而是在其值节点之一更新时更新。这是递归进行的,因此内部 SumNodes 也会触发更新。由于通知包含节点的唯一 id,因此可以编写更复杂的 Node 类型,例如包含公式的类型。

请参阅 http://www.ruby-doc.org/stdlib/ libdoc/observer/rdoc/index.html 有关 Observable 的更多详细信息

This sounds like a good situation for the observer pattern. This is a sample of that in ruby:

require 'observer'

class Node
  attr_accessor :id
  @@current_node_id = 0
  def initialize
    @@current_node_id += 1
    id = @@current_node_id
  end
  include Observable

  attr_reader :value


  protected
  def value=(new_value)
    return if @value == new_value
    old_value = @value
    @value = new_value
    changed
    notify_observers(id, old_value, @value)
  end
end


class ValueNode < Node
  def initialize(initial_value)
    super()
    @value = initial_value
  end

  def value=(new_value)
    super(new_value)
  end
end


class SumNode < Node
  def initialize(*nodes)
    super()
    @value = nodes.map(&:value).inject(0, &:+)
    nodes.each do |node|
      node.add_observer(self)
    end
  end


  def update(id, old_value, new_value)
    self.value = self.value - old_value + new_value
  end
end


def test
  v1 = ValueNode.new 4
  v2 = ValueNode.new 8
  sum = SumNode.new(v1, v2)
  sum2 = SumNode.new(v1, sum)
  v2.value = 10
  p sum.value
  p sum2.value
end


test()

Notice how the value of SumNode isn't recalculated every time it is requested - instead it is updated when one of its value nodes is updated. This works recursively, so that inner SumNodes also trigger updates. As the notification includes the unique id of the node, it is possible to write more complex Node types, such as ones that contain formulas.

See http://www.ruby-doc.org/stdlib/libdoc/observer/rdoc/index.html for more details on Observable

淡莣 2024-11-24 10:52:44

这听起来类似于常用的 Twitter 范例,其中一个用户的更新会推送给其所有关注者。为了有效地做到这一点,您应该为给定的人存储两个列表:一个包含他关注的人,另一个包含关注他的人。您可以对节点列表执行相同的操作。当节点发生变化时,可以快速查找受该节点影响的节点。当关系消失时,您将需要“正向”列表来知道从哪些列表中“删除”反向关系。

您可以将这些列表存储在二维数组中,或者存储在 Redis 之类的地方。我真的不明白 EventMachine 如何融入其中。

This sounds similar to the oft-used Twitter paradigm, where updates by one user are pushed to all it's followers. To do this efficiently, you should store two lists for a given person: one with the people he follows and one with the people that follow him. You can do the same for a list of nodes. When a node changes you can quickly look up the nodes that are influenced by this node. When a relationship disappears you will need the 'forward' list to know from which lists to 'remove' the reverse relationship.

You can store these lists two-dimensional arrays, or in something like Redis. I don't really understand how EventMachine would fit in.

烟花易冷人易散 2024-11-24 10:52:44

如果您有依赖关系的网络图并且希望它们能够扩展,那么图数据库是最好的解决方案。 Neo4J 是一个流行的、功能强大的数据库,用于跟踪此类依赖关系。

有多种方法可以从 Ruby 与 Neo4J 进行交互:

  • 您可以使用 JRuby 及其 java 接口。
  • 使用其 REST API
  • 使用 neo4j.rb 或其他 Ruby 接口库之一。

If you have a network graph of dependencies and you want them to scale, a graph database is the best solution. Neo4J is a popular, powerful database for tracking this type of dependencies.

There are several ways to interface with Neo4J from Ruby:

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