views:

117

answers:

5

And there could be many levels, who knows how deep it could go! Also let's say for this specific question that the String for another Dictionary will be "Dictionary" and a value that I want to access/modify will be "Data".

+1  A: 

Basically, yes. You'd have to test each value against the types you're willing to iterate through, by casting them with as.

Steven Sudit
LBushkin is correct; any recursive function can be replaced by an iterative function if we're willing to make an explicit stack.
Steven Sudit
+1  A: 

I am going to have to go with "yes" this would be the quickest and easiest to write. something like this....

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;
}
Muad'Dib
What, what? Mixing return and yield return? I think not!
Chris Shouts
@Chris Shouts, thanx, fixed.
Muad'Dib
@Muad'Dib, still totally wrong. The return type is string (not IEnumerable<String>), and contains a plain return, which is not allowed.
Dykam
well, it is demo code and i didnt run it through my compiler, but it give the OP the gist of a solution. <sigh> it IS monday, after all. :)
Muad'Dib
So fix it to make it work.
Steven Sudit
+1  A: 

Recursion is generally the most code-efficient way to traverse a tree structure of unknown depth. Is there some reason you can't use recursion? It sounds as if you're looking for some other option as if a recursive algorithm doesn't meet some requirement.

KeithS
A: 

It's not essential to recurse. You can do this using Linq as shown by concrete extension methods to make virtually any tree searchable by Linq.

Steve Townsend
+4  A: 
LBushkin
Ok, but what would the advantage of an explicit stack be here? To allow deeper nesting? I'm not sure whether, in practice, the standard stack size is ever going to be too small for a non-infinite nesting.
Steven Sudit
@Steven: I don't know the details of the callers data structure. Only the caller does. My purpose was to answer the question posed: whether recursion is *necessary* to implement the traversal. It is not. I mention my guidance for when to use an explicit stack vs. recursion in my last paragraph. I will add here, however, that iterative implementations can sometimes be easier to debug than recursive ones - only seeing one call level in the debugger makes it easier to get your bearings than trying to walk back through 10, 20, or more levels of recursive calls.
LBushkin
@Steven The thread stack is usually ~1MB in size. By using an explicit stack, as @LBushkin did, he can support nesting levels that could consume GB of memory (assuming a 64-bit address space). So yes, certainly, both will have limits, but the practical limits of the non-recursive solution are significantly higher than the recursive solution. That said, the lower limits of actual recursion might not matter, and I find "normal" recursion easier to write.
jonp
@LBushkin: Ok, I already conceded that an explicit stack can be of arbitrary size. But my point remains: in practice, do you really expect to use up a whole megabyte unless you're stuck in an infinite loop? As for being easier to debug, it involves writing more code that needs debugging, so I'm not sure that it's a net gain.
Steven Sudit
@jonp: Yes, for recursively-defined data structures, recursive code is often more natural. The issue of stack use might not come up, due to tail end optimization (available in the 64-bit CLR only).
Steven Sudit
@Steven: Are you looking for an answer other than *it depends*? My general advice to anyone writing code is: *"Make the implementation as simple, clear, and relatable to the problem as possible while still working for the expected use cases"*. Does recursion fit that? Sure. And in most cases a recursive implementation is the right way to go. But there do exist cases where it's useful to know and use iterative forms instead. Case in point: here's a recent post by Eric Lippert http://stackoverflow.com/questions/3713082/iterator-block-to-linq/3719165#3719165 with some analysis on the reasons.
LBushkin
@LBushkin: Yes, I was familiar with that post; you might note that I commented on it. Anyhow, I don't know that we're disagreeing. Mostly, we're airing out the argument so that we can move past "it depends" to "it depends on the following...", with specifics. :-)
Steven Sudit
@Steven: Specifics can certainly be helpful :-). I don't disagree with your premise that in most cases recursion is the appropriate implementation approach for these kinds of problems. However, I have a harder time "distilling" the rules by which to decide when to use it. Software engineering is still 4 parts science, 1 part art.
LBushkin
@LBushkin: Probably why we haven't been replaced by software. Yet.
Steven Sudit