1

I built a data structure where the main class, TaskHolder, contains a List<Task> and Task contains another List<Task> and Name. is there a LINQ one line code that can retrieve all nested Names into a flattened string array?

this is the basic structure:

Public class TaskHolder
  List<Task>

Public class Task
  String Name
  List<Task>
yaron hochman
  • 207
  • 1
  • 3
  • 7

2 Answers2

3

It looks like you can't achieve it without recursion. It can be something like this:

    static IEnumerable<string> Flatten(Task task)
    {
        return new[] {task.Name}.Concat(task.Tasks.SelectMany(Flatten));
    }

    //.. and then
    var allNames = Flatten(taskHolder.Task);
ie.
  • 5,982
  • 1
  • 29
  • 44
  • 1
    @MartinLiversage and why shouldn't recursion look recursive? ;) – ie. Jan 24 '15 at 11:12
  • Works like a charm. I encapsulated this Helper with a for each loop to iterate all tasks in the list and concatanated it all into a IEnumerable. – yaron hochman Jan 24 '15 at 11:28
0

You can also write your own LINQ extension method to do this kind of thing, and use something like a stack to avoid explicit recursion (better if the nesting is very deep):

  public static class LinqExtensions
  {
    public static IEnumerable<TP> FlattenProperties<T, TP>(this IEnumerable<T> outers,
        Func<T, TP> propertySelector, Func<T, IEnumerable<T>> innersSelector)
    {
      Stack<T> stack = new Stack<T>(outers);
      while (stack.Any())
      {
        T outer = stack.Pop();

        TP prop = propertySelector(outer);
        yield return prop;
        if (innersSelector(outer) != null)
        {
          foreach (var inner in innersSelector(outer))
            stack.Push(inner);
        }
      }
    }
  }

You can then write something like:

TaskHolder th = new TaskHolder() { ... };
var names = th.Tasks.FlattenProperties(x => x.Name, x => x.Tasks).ToList();
Patrice Gahide
  • 3,644
  • 1
  • 27
  • 37