0

I have a list of Person objects. Each Person has a list of Persons as a property. Here's the class.

 public class Person
 {       
     public List<Person> Team { get; set; }
     public string Status {get; set;}
 }

So each person has a parent, a list of children, and a status.

I need to count the number of times the status equals "X" or "Y" in a given person's tree. I was told I could use the .Aggregate() function, but I'm not sure how I would do that.

For example, if a Person had a list of 3 people all with status "X" and each of those people had lists of 3 people, 2 with status "X" and 1 with status "Z", that would be 12 people total and the count of "X" would be 9.

joelforsyth
  • 836
  • 1
  • 11
  • 28
  • In case of a tree (which is a kind of recursive data structure), you should consider using recursive methods to navigate through it. Linq is more suitable for sequential structures, or to reach a specific depth in a tree (which in fact is a kind of sequential navigation). – Kryptos May 11 '15 at 15:35
  • Is your graph cyclic? – Servy May 11 '15 at 15:38
  • @Servy assuming the OP used the term "tree" correctly, then trees are acyclic by definition. – dcastro May 11 '15 at 15:42
  • @dcastro Enough people use that term incorrectly that I felt it merited verifying that assumption. But yes, you are correct. – Servy May 11 '15 at 15:45
  • @Servy fair enough, after a while you learn to validate those assumptions :) – dcastro May 11 '15 at 15:46

1 Answers1

4

You could recursively "flatten" your tree, like this for example (using a post-fix iterator):

public class Person
{
    public List<Person> Team { get; set; }
    public string Status { get; set; }

    public IEnumerable<Person> Flatten()
    {
        yield return this;

        foreach (var person in Team)
            foreach (var child in person.Flatten())
                yield return child;
    } 
}

And then, using a "root" person, you could do this:

var count = person.Flatten().Count(p => p.Status == "X" || p.Status == "Y");

If you had a collection of people, you could combine SelectMany with Flatten.

people.SelectMany(p => p.Flatten()).Count(...)
dcastro
  • 66,540
  • 21
  • 145
  • 155