Итерировать в потомки, если переменная по-прежнему равна нулю - PullRequest
0 голосов
/ 13 марта 2019

У меня есть метод 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 все еще нулевой), он выглядит как потомкиparent, и если он по-прежнему равен нулю, он смотрит на childs of child.

Код работает, но его слишком сложно прочитать, есть ли лучший способ реализовать эту итерацию?

1 Ответ

0 голосов
/ 13 марта 2019

Звучит так, как будто вы ищете здесь поиск в ширину , где вы сначала просматриваете всех детей, затем детей каждого ребенка и т. Д., Пока не найдете совпадение.

Для этого типа поиска мы хотим использовать 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 методу вместе с функцией проверки (в этом примере я передаю лямбду)выражение для функции проверки):

TreeNode firstMatch = GetFirstMatch(treeView1.Nodes,
    node => node.Tag.ToString().Split('|')[0].Equals(designKey.ToString()));
...