All the solutions posted so far are specialized - they are not generic or general, and thus, the next time you have a hierarchical list, you'll have to code up a new solution. Yuck.
Here's a general, generic solution that will work for all your hierarchical needs:
public static IEnumerable<T> Flatten<T>(this IEnumerable<T> sequence, Func<T, IEnumerable<T>> childFetcher)
{
var itemsToYield = new Queue<T>(sequence);
while (itemsToYield.Count > 0)
{
var item = itemsToYield.Dequeue();
yield return item;
var children = childFetcher(item);
if (children != null)
{
foreach (var child in children)
{
itemsToYield.Enqueue(child);
}
}
}
}
Here's how you'd use it:
myList.Flatten(i => i.SubEntries).FirstOrDefault(i => i.HighScore);
Easy as cheese.
This extension method can be used to turn any hierarchical data into a flat list, which can them be searched using LINQ.
Another great thing about this solution is that is uses lazy evaluation, thus it only does as much work as the caller demands. For example, in the above code, Flatten will stop churning out items as soon as a HighScore is found.
This solution also avoids recursion, which can be a costly operation for deeply nested hierarchies, avoiding the many stack allocations that recursive solutions incur.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…