patterncsharpMinor
Search for Tree
Viewed 0 times
treeforsearch
Problem
Here is a search implementation for my tree. It searches each node in a breadth-first manner first, but it goes deeper in a depth-first manner, in the event it needs to go deeper. I know there may be multiple identical items in the tree (well, not my current use of it, but I still need to presume that), so it just returns the children for the first instance found. If I ever have duplicate items with different children, there will be other things needing change anyway.
For reference, this method is being implemented as part of my tree here: Trees and their uses
I'm sure there are ways I can improve this, although it looks good to me.
Edit:
Some people asked me for clarification on how my search combined the breadth-first and depth-first searches in The 2nd Monitor. Here are some images showing how they each work (the first two taken from Wikipedia):
Breadth-first search:
Depth-first search:
My search:
For reference, this method is being implemented as part of my tree here: Trees and their uses
public IEnumerable GetChildren(T item)
{
IEnumerable> itemSet = items.Where(x => item.Equals(x.Value));
if (itemSet.Count() != 0)
{
int index = itemSet.ElementAt(0).Key;
IEnumerable>> branchSet = branches.Where(x => x.Key == index);
if (branchSet.Count() != 0)
{
return branchSet.ElementAt(0).Value.GetChildren();
}
}
foreach (KeyValuePair> kvp in branches)
{
IEnumerable coll = kvp.Value.GetChildren(item);
if (coll != Enumerable.Empty())
{
return coll;
}
}
return Enumerable.Empty();
}I'm sure there are ways I can improve this, although it looks good to me.
Edit:
Some people asked me for clarification on how my search combined the breadth-first and depth-first searches in The 2nd Monitor. Here are some images showing how they each work (the first two taken from Wikipedia):
Breadth-first search:
Depth-first search:
My search:
Solution
- I would use
First()instead ofElementAt(0)as it conveys the intention better.
- Instead of using
something.Count() != 0you should usesomething.Any(). This avoids having to iterate over the entire sequence just to find out if there are any items in it.
- Also you are not interested in the entire
itemSetyou're just interested in the first one if it exists so you should make use ofFirstOrDefaultwhich also provides a predicate overload.
-
This
foreach loop:foreach (KeyValuePair> kvp in branches)
{
IEnumerable coll = kvp.Value.GetChildren(item);
if (coll != Enumerable.Empty())
{
return coll;
}
}can be condensed to:
var result = branches.Select(kvp => kvp.Value.GetChildren(item))
.FirstOrDefault(coll => coll != Enumerable.Empty());
return result ?? Enumerable.Empty();Update: Due to
KeyValuePair being a value type to make it a bit neater a little helper is needed:public static class Extensions
{
public static bool EqualsDefault(this T obj)
{
return EqualityComparer.Default.Equals(obj, default(T));
}
}With this the method could be rewritten as:
public IEnumerable GetChildren(T item)
{
var firstMatch = items.FirstOrDefault(x => item.Equals(x.Value));
if (!firstMatch.EqualsDefault())
{
var branch = branches.FirstOrDefault(x => x.Key == firstMatch.Key);
if (!branch.EqualsDefault())
{
return branch.Value.GetChildren(item);
}
}
var result = branches.Select(kvp => kvp.Value.GetChildren(item))
.FirstOrDefault(coll => coll != Enumerable.Empty());
return result ?? Enumerable.Empty();
}Code Snippets
foreach (KeyValuePair<int, Tree<T>> kvp in branches)
{
IEnumerable<T> coll = kvp.Value.GetChildren(item);
if (coll != Enumerable.Empty<T>())
{
return coll;
}
}var result = branches.Select(kvp => kvp.Value.GetChildren(item))
.FirstOrDefault(coll => coll != Enumerable.Empty<T>());
return result ?? Enumerable.Empty<T>();public static class Extensions
{
public static bool EqualsDefault<T>(this T obj)
{
return EqualityComparer<T>.Default.Equals(obj, default(T));
}
}public IEnumerable<T> GetChildren(T item)
{
var firstMatch = items.FirstOrDefault(x => item.Equals(x.Value));
if (!firstMatch.EqualsDefault())
{
var branch = branches.FirstOrDefault(x => x.Key == firstMatch.Key);
if (!branch.EqualsDefault())
{
return branch.Value.GetChildren(item);
}
}
var result = branches.Select(kvp => kvp.Value.GetChildren(item))
.FirstOrDefault(coll => coll != Enumerable.Empty<T>());
return result ?? Enumerable.Empty<T>();
}Context
StackExchange Code Review Q#85742, answer score: 4
Revisions (0)
No revisions yet.