我有这样的foreach方法:
TreeNode selectedNode = null;
foreach (TreeNode tn in allNodes)
{
if (selectedNode != null) continue;
var designNodes = tn.Nodes;
foreach (TreeNode item in designNodes)
{
if (item.Tag.ToString().Split('|')[0].Equals(designKey.ToString()))
{
selectedNode = item;
continue;
};
if (selectedNode is null)
{
foreach (TreeNode child in item.Nodes)
{
if (child.Tag != null && child.Tag.ToString().Split('|')[0].Equals(designKey.ToString()))
{
selectedNode = child;
continue;
}
if (selectedNode is null)
{
foreach (TreeNode lastLevel in child.Nodes)
{
if (lastLevel.Tag != null && lastLevel.Tag.ToString().Split('|')[0].Equals(designKey.ToString()))
{
selectedNode = lastLevel;
continue;
}
}
}
}
}
}
}
首先,它迭代到TreeNode父级并分配变量selectedNode
,如果它没有找到结果(selectedNode
仍为null),它看起来是父级的子级,如果它仍然为null,则查看子级的子级。
编码它的工作,但它太难阅读,有一个最好的方法来实现这个迭代?
听起来你在这里寻找的是一个广度优先的搜索,你首先搜索所有的孩子,然后搜索每个孩子的孩子等,直到找到匹配。
对于这种类型的搜索,我们想要使用Queue
,它是“先进先出”(而不是堆栈,这是“后进先出”)。这样我们可以将Enqueue
根TreeNode
项目放入队列,然后在循环中我们Dequeue
每个项目一次,检查它是否有效,如果它是,如果它不是我们Enqueue
它的孩子。这确保了我们总是在孩子面前检查父母。
通过允许客户端传入将用于验证validator
的TreeNode
函数,我已经使这个方法更灵活一些。通过这种方式,我们可以重复使用该方法对我们希望的任何条件进行广度优先搜索(我们只是传递一个接收TreeNode
的方法,并返回bool
,如果该节点的验证成功,则为true
):
private static TreeNode GetFirstMatch(TreeNodeCollection allNodes,
Func<TreeNode, bool> validator)
{
if (allNodes == null) return null;
// Initialize a Queue with all the root nodes
var nodeQueue = new Queue<TreeNode>(allNodes.OfType<TreeNode>());
// Use a queue for a breadth-first search
while (nodeQueue.Any())
{
// Remove the next item
var current = nodeQueue.Dequeue();
// Return it if it passes our validation
if (validator.Invoke(current)) return current;
// Add it's children to the end of the queue
foreach (TreeNode child in current.Nodes)
{
nodeQueue.Enqueue(child);
}
}
// If we didn't find any matches, return null
return null;
}
在使用中,我们可以将Nodes
控件的TreeView
属性与验证函数一起传递给方法(在此示例中,我传递了验证函数的lambda表达式):
TreeNode firstMatch = GetFirstMatch(treeView1.Nodes,
node => node.Tag.ToString().Split('|')[0].Equals(designKey.ToString()));