Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get a flattened list from nested class List<T>?

I have a question using these same examples - this question is focused on a different issue. Given the following classes:

   [XmlRoot]
   public class Family {

      [XmlElement]
      public List<Person> Person;
   }

   public class Person {

      [XmlAttribute("member")]
      public MemberType Member { get; set; }

      [XmlAttribute("id")]
      public int Id { get; set; }

      [XmlElement]
      public string Surname { get; set; }

      [XmlElement]
      public string Forename { get; set; }

      [XmlElement("Person")]
      public List<Person> People;
   }

   public enum MemberType {
      Father,
      Mother,
      Son,
      Daughter
   }

If Family has a method defined as such:

public IEnumerable<Person> Find (Func<Person, bool> predicate) {
    //  how do I get SelectMany to flatten the list?
    foreach (var p in family.Person.SelectMany(p => p)) {
        if(predicate(p)) {
            yield return p;
        }
    }
}

I need to be able to execute the predicate over a flattened list of Person. In the example above SelectMany is not flattening the list as I had hoped. The above actually won't compile because the inferred type cannot be determined.

How can I get the Family.Person collection to become one flattened list of Person?

like image 883
IAbstract Avatar asked Jan 12 '12 16:01

IAbstract


People also ask

How do you make a list of lists flat listed?

Flatten List of Lists Using sum. Summing over inner lists is another solution. The function has two parameters: iterable which is a list of lists and start which is an empty list in our case that serves as the initial flat list to which items of the inner sublists are added.

How do I remove a nested list in Python?

Flatten the list to "remove the brackets" using a nested list comprehension. This will un-nest each list stored in your list of lists!


1 Answers

To my knowledge, the easiest way to accomplish this is using a helper.

    private List<Person> FlattenTree(Person person)
    {
        var accumulator = new List<Person>();
        FlattenPersonHelper(person, accumulator);

        return accumulator;
    }


    private void FlattenPersonHelper(Person person, List<Person> accumulator)
    {
        accumulator.Add(person);

        foreach (var child in person.People)
        {
            FlattenPersonHelper(child, accumulator);
        }
        return;
    }

You can then run your predicate against this list:

public IEnumerable<Person> Find (Func<Person, bool> predicate) {
    var familyRoot = new Person() { People = family.Person };
    return FlattenTree(familyRoot).Where(predicate);
}
like image 127
armen.shimoon Avatar answered Nov 04 '22 06:11

armen.shimoon