Выполнить итерацию с дочерними элементами, если переменная по-прежнему равна нулю

#c# #iteration #treenode

#c# #итерация #treenode

Вопрос:

У меня есть метод 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 amp;amp; 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 amp;amp; lastLevel.Tag.ToString().Split('|')[0].Equals(designKey.ToString()))
                                        {
                                            selectedNode = lastLevel;
                                            continue;
                                        }
                                    }
                                }

                            }

                        }

                    }
                }   
  

Сначала выполняется итерация в родительский элемент TreeNode и присваивается переменная selectedNode , если она не нашла результатов ( selectedNode по-прежнему равна нулю), она просматривает дочерние элементы родительского элемента, и если она по-прежнему равна нулю, она просматривает дочерние элементы дочернего элемента.

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

Комментарии:

1. if (selectedNode is null) должно быть if (selectedNode == null)

2. Извините, я обновляю свой вопрос @RufusL

3. Не должны ли continue; строки быть break; вместо этого? Похоже, что именно там вы нашли правильное соответствие. Зачем продолжать? Кроме того, цель здесь — найти первый узел, который удовлетворяет Tag == designKey условию? Или что-то еще?

4. Да, если он назначает переменную lastDesign, которую я использую, продолжает прерываться, и она должна завершить назначение @RufusL

5. continue не прерывается, though…it просто пропускает остальную часть этой итерации и затем продолжает цикл. break произойдет выход из цикла. Не могли бы вы, пожалуйста, конкретно определить, что должен делать код?

Ответ №1:

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

Для этого типа поиска мы хотим использовать 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()));