Нужна ли мне рекурсивная функция для перебора словаря?словаряs? - PullRequest
2 голосов
/ 21 сентября 2010

И может быть много уровней, кто знает, как глубоко это может пройти!Также давайте скажем для этого конкретного вопроса, что строка для другого словаря будет «Словарь», а значение, к которому я хочу получить доступ / изменить, будет «Данные».

Ответы [ 5 ]

4 голосов
/ 21 сентября 2010

Потребуется ли мне рекурсивная функция для итерации Dictionary<String, Object> из Dictionary<String, Object> с?

Нет. Любая рекурсивнаяАлгоритм может быть переписан для использования явного стека, а не стека вызовов.

Легче ли использовать рекурсию для этого?

Возможно. Однако, если структура очень глубоко вложена (или содержит циклы), вы можете подвергнуться риску исключения переполнения стека.

Нерекурсивная реализация не особенно сложна в реализации.Это потребует от вас ведения списка (стека или очереди, в зависимости от того, в каком порядке вы хотите посещать детей), который отслеживает под-словари, которые еще предстоит посетить.

Прототип (не рекурсивный) реализация будет выглядеть примерно так:

public IEnumerable<string> GetAllKeys( Dictionary<string,object> dictionary )
{
    var stackDictionariesToVisit = new Stack<Dictionary<string,object>>();

    stackDictionariesToVisit.Push( dictionary );

    // keep visiting iterating until the stack of dictionaries to visit is empty
    while( stackDictionariesToVisit.Count > 0 )
    {
        var nextDictionary = stackDictionariesToVisit.Pop();
        foreach( var keyValuePair in nextDictionary )
        {
            if( keyValuePair.Value is Dictionary<string,object> )
            {
                stackDictionariesToVisit.Push( 
                     keyValuePair.Value as Dictionary<string,object> );
            }
            else
            {
                yield return keyValuePair.Key;
            }
        }
    }
}

Приведенная выше реализация не проверяет ошибки и не проверяет циклы, но заменяет рекурсию явным стеком.

Выбор того, использовать ли рекурсию (или нет) для посещения иерархической структуры данных, должен зависеть от понимания типа хранимых данных, а не от того, какой подход проще. Если у вас глубоко вложенная структура, вам лучшеoff NOT с использованием рекурсии, поскольку вы не можете контролировать, сколько места в стеке у вас будет.С другой стороны, если вы уверены, что данные никогда не будут вложены более чем на несколько уровней, рекурсивная реализация может быть (немного) проще для понимания и поддержки.

1 голос
/ 21 сентября 2010

Мне нужно сказать «да», это было бы самым быстрым и простым для написания как то так ....

string WalkIt( Dictionary<string,object> data )
{
    if ( data == null ) yield return null;

    foreach (KeyValuePair<string, object> kvp in data)
    {
        if (kvp.Value is string)
        {
            yield return kvp.Value;
        }

        if (kvp.Value is Dictionary<string, object>)
        {
            foreach( string str in walk(kvp.Value as Dictionary<string, object>))
                 yield return str;
        }
            }
        }
       yield return null;
}
1 голос
/ 21 сентября 2010

Рекурсия, как правило, наиболее эффективный для кода способ обхода древовидной структуры неизвестной глубины.Есть ли причина, по которой вы не можете использовать рекурсию?Звучит так, как будто вы ищете какую-то другую опцию, как будто рекурсивный алгоритм не удовлетворяет некоторым требованиям.

1 голос
/ 21 сентября 2010

В основном да. Вам нужно проверить каждое значение на соответствие типам, которые вы хотите перебрать, приведя их к as.

0 голосов
/ 21 сентября 2010

Нет необходимости возвращаться. Вы можете сделать это, используя Linq, как показано конкретными методами расширения, чтобы Linq .

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