graph/iterator: implement edge and line based lazy node iterator

This commit is contained in:
Dan Kortschak
2020-06-05 15:50:40 +09:30
parent c8de933feb
commit d4ef54c821
2 changed files with 397 additions and 0 deletions

View File

@@ -178,3 +178,100 @@ func (n *Nodes) Reset() {
n.pos = 0
n.iter = n.nodes.MapRange()
}
// NodesByEdge implements the graph.Nodes interfaces.
// The iteration order of Nodes is randomized.
type NodesByEdge struct {
nodes map[int64]graph.Node
edges reflect.Value
iter *reflect.MapIter
pos int
curr graph.Node
}
// NewNodesByEdge returns a NodesByEdge initialized with the
// provided nodes, a map of node IDs to graph.Nodes, and the set
// of edges, a map of to-node IDs to graph.Edge, that can be
// traversed to reach the nodes that the NodesByEdge will iterate
// over. No check is made that the keys match the graph.Node IDs,
// and the map keys are not used.
//
// Behavior of the NodesByEdge is unspecified if nodes or edges
// is mutated after the call the NewNodes.
func NewNodesByEdge(nodes map[int64]graph.Node, edges map[int64]graph.Edge) *NodesByEdge {
rv := reflect.ValueOf(edges)
return &NodesByEdge{nodes: nodes, edges: rv, iter: rv.MapRange()}
}
// NewNodesByWeightedEdge returns a NodesByEdge initialized with the
// provided nodes, a map of node IDs to graph.Nodes, and the set
// of edges, a map of to-node IDs to graph.WeightedEdge, that can be
// traversed to reach the nodes that the NodesByEdge will iterate
// over. No check is made that the keys match the graph.Node IDs,
// and the map keys are not used.
//
// Behavior of the NodesByEdge is unspecified if nodes or edges
// is mutated after the call the NewNodes.
func NewNodesByWeightedEdge(nodes map[int64]graph.Node, edges map[int64]graph.WeightedEdge) *NodesByEdge {
rv := reflect.ValueOf(edges)
return &NodesByEdge{nodes: nodes, edges: rv, iter: rv.MapRange()}
}
// NewNodesByLines returns a NodesByEdge initialized with the
// provided nodes, a map of node IDs to graph.Nodes, and the set
// of lines, a map to-node IDs to map of graph.Line, that can be
// traversed to reach the nodes that the NodesByEdge will iterate
// over. No check is made that the keys match the graph.Node IDs,
// and the map keys are not used.
//
// Behavior of the NodesByEdge is unspecified if nodes or lines
// is mutated after the call the NewNodes.
func NewNodesByLines(nodes map[int64]graph.Node, lines map[int64]map[int64]graph.Line) *NodesByEdge {
rv := reflect.ValueOf(lines)
return &NodesByEdge{nodes: nodes, edges: rv, iter: rv.MapRange()}
}
// NewNodesByWeightedLines returns a NodesByEdge initialized with the
// provided nodes, a map of node IDs to graph.Nodes, and the set
// of lines, a map to-node IDs to map of graph.WeightedLine, that can be
// traversed to reach the nodes that the NodesByEdge will iterate
// over. No check is made that the keys match the graph.Node IDs,
// and the map keys are not used.
//
// Behavior of the NodesByEdge is unspecified if nodes or lines
// is mutated after the call the NewNodes.
func NewNodesByWeightedLines(nodes map[int64]graph.Node, lines map[int64]map[int64]graph.WeightedLine) *NodesByEdge {
rv := reflect.ValueOf(lines)
return &NodesByEdge{nodes: nodes, edges: rv, iter: rv.MapRange()}
}
// Len returns the remaining number of nodes to be iterated over.
func (n *NodesByEdge) Len() int {
return n.edges.Len() - n.pos
}
// Next returns whether the next call of Node will return a valid node.
func (n *NodesByEdge) Next() bool {
if n.pos >= n.edges.Len() {
return false
}
ok := n.iter.Next()
if ok {
n.pos++
n.curr = n.nodes[n.iter.Key().Int()]
}
return ok
}
// Node returns the current node of the iterator. Next must have been
// called prior to a call to Node.
func (n *NodesByEdge) Node() graph.Node {
return n.curr
}
// Reset returns the iterator to its initial state.
func (n *NodesByEdge) Reset() {
n.curr = nil
n.pos = 0
n.iter = n.edges.MapRange()
}