Sunday, May 09, 2010

LINQ challenge - an answer

Someone asked for an answer to the LINQ challenge I posted a while back.  The following is an answer to the "find all descendants of a given Parent" part of the challenge.  It cheats a little, in that it makes use of a variable external to the method (stack), but it prints out the descendants of whatever parent you feed it, so that's good. 

This is not the only way to get an answer to this particular problem, and I certainly don't guarantee it's the best.

Incidentally, if anybody knows a utility for HTML-formatting code examples in a Blogger-friendly way, I'd like to hear about it.

Assume a class called ForeignKey that has two fields, both strings, called ParentTable and ChildTable.  Assume also a variable list
defined earlier in the routine, that is declared as List<ForeignKey>

Action<string, int> f = null;
Stack<string> stack = new Stack<string>();

f = (table, level) => 
    {
    stack.Push(table);
    list.Where(fk => fk.ParentTable.Equals(table))
        .Where(fk => stack.Contains(fk.ChildTable) == false)
        .ToList()
        .ForEach(fk=> {
                        Console.WriteLine("{0}: {1}", level, fk.ChildTable);
              f(fk.ChildTable, level + 1);
        });
    stack.Pop();
      };

You might be curious about what the level and stack variables are doing here.  The level parameter is so we have some way to indicate how many levels deep we are:  otherwise, we'd just be printing table names and not know where in the structure we were.  But if you don't care, leave it out.

The stack variable is there to guard against "loops", where a "descendant" of one parent is ultimately itself an ancestor of that parent.  If your hierarchy is one that cannot have any loops (say, a family tree) then you don't need to guard against them.  But it's a decent idea to do so anyway, in case your data has been corrupted. 

0 Comments:

Post a Comment

<< Home