我正在尝试开发一种反应式 DFS 实现,它可以产生不同的节点,而不需要遍历不必要的路径。树可能包含重复/相等的节点。如果一个节点已经被遍历,那么它的所有子节点也都被遍历了,因此如果我们再次遇到一个节点,我们可以停止扩展遍历。
class Traversal {
//exposed method with understandable signature
public IObservable<Node> DepthFirst(Node root) {
return DepthFirstRecursive(root, new List<Node>(), new SomeStatefulHelper());
}
//hidden method with accumulator for cutting
private IObservable<Node> DepthFirstRecursive(Node root, List<Node> accuFilter, SomeHelper helper) {
return root.GetChildren().AsObservable()
//here we cut traversal:
.Where(n => !accuFilter.Contains(n))
//cannot do SelectMany, because we want sequential processing:
.Select(n => DepthFirstRecursive(n, accuFilter, helper)).Concat()
.Concat(Observable.Return(root))
//adding results to accumulator
.Do(accuFilter.Add)
}
}
class Node : IEquatable<Node> {
public IEnumerable<Node> GetChildren(SomeHelper helper) {
//produce child nodes
}
...
}
蓄能器并不漂亮。它基本上是通过其他优雅的响应式实现编织的副作用。如何使用 Rx 摆脱它? Observable.Distinct()
不会削减它(双关语),因为它只能在链的最末端(在哪里.Do
)运行。
此外,使用助手,我=>
在.Where
. 我不认为这个警告是相关的。是吗?我该如何摆脱它?