0

名前とノードの配列を持つ非常に単純なノード クラスを作成しました。また、各ノードと子ノードを反復処理するのに役立つ next メソッドを使用して iterator クラスを作成しました。次のメソッドを書く必要がありますが、それを行う最善の方法がわかりません。

class Node

  def initialize(name, nodes
    @name = name
    @nodes = nodes
  end
end

class Iterator
  def initialize(node)
    @node = node
  end

  def next
    ???
  end
end

例:

z = Node.new("z", [])
b = Node.new("b", [z])    
c = Node.new("c", [])
parent = Node.new("a", [b, c]) 

iterator = Iterator.new(parent)
str = ''
next = iterator.next
while next do
 str += next.name
 next = iterator.next
end

str は "abzc" に等しい必要があります

誰でもこれで私を助けることができますか?

4

4 に答える 4

6

もっと慣用的なアプローチを提案する場合:

class Node

  attr_accessor :name, :children

  def initialize(name, children = [ ])
    @name = name
    @children = children
  end

  def traverse(&block)
    yield self
    @children.each { |child| child.traverse(&block) }
  end

end

z = Node.new("z")
b = Node.new("b", [z])
c = Node.new("c")
parent = Node.new("a", [b, c])

str = ''
parent.traverse { |node| str += node.name }
puts str

これは、イテレータオブジェクトを増殖させたり、メモリを消費したりしないという点で、btillyのソリューション(これも正しい)よりも優れています。実際、イテレータは実装から消えます(ただし、各ノードに対して連続して何かを実行する機能は保持されます)。これはもっと慣用的です。もっとRuby風。

于 2012-05-19T04:56:27.050 に答える
0

イテレータでは、 node に子がある場合、 next が最初の子になります。そうでない場合は、スキップした最後の兄弟に「バックアップ」する必要があります。これは、スキップされた兄弟を追跡して、それらに戻ることができるようにする必要があることを意味します。

于 2012-05-19T02:00:56.490 に答える
0

これは、あなたが探していると私が思うものを示す実行中のコードです。

class Node
  attr_accessor :name, :nodes

  def initialize(name, nodes)
    @name = name
    @nodes = nodes
  end
end

class Iterator
  def initialize(node)
    @node = node
  end

  def each_node
    yield @node
    for node in @node.nodes do
      iterator = Iterator.new(node)
      iterator.each_node {|next_node|
        yield next_node
      }
    end
  end
end

z = Node.new("z", [])
b = Node.new("b", [z])
c = Node.new("c", [])
parent = Node.new("a", [b, c])

iterator = Iterator.new(parent)
str = ''
iterator.each_node {|node|
  str += node.name
}
puts str
于 2012-05-19T02:21:39.113 に答える
0

以下を実行することで問題を解決できました。しかし、このアプローチで気に入らないのは、次のメソッドではなく、初期化中にノードをトラバースすることです...

class Iterator

  def initialize(node)
    @node   = node
    @index  = -1
    @list   = []

    traverse(@node)
  end

  def next
    @index += 1
    @list[@index]
  end

  private
  def traverse(root)
    @list[@list.size] = root
    if root.nodes
      for n in root.nodes do
        traverse(n)
      end
    end  
  end

end
于 2012-05-19T19:22:02.187 に答える