Generic Collections and Filtering




- May 29, 2017

Rest of the Story:

When dealing with collections the common question is how to filter them based on criteria. 

The following are a few techniques used to accomplish this. A delegate is like a function pointer. 

A predicate is a method that returns true or false. 

In the case of List<T> it is possible to pass it a delegate that is a function that returns true or false.

In the examples below I have base object a generic collection of those objects and am using the FindAll method to return only a few of the objects based on matching criteria.  There are a number of samples, just un-comment the ones of interest.

   23             Persons personList = new Persons();    24             Person p1 = new Person("Rose", "Bob");    25             Person p2 = new Person("Rose", "Phil");    26             Person p3 = new Person("Smith", "Jack");    27             personList.Add(p1);    28             personList.Add(p2);    29             personList.Add(p3);    30     31             //Sample 1 Using Predicate Technique (long form)    32             //Predicate<Person> filterByLastName;    33             //PersonFilter filter = new PersonFilter("Rose");    34             //filterByLastName = new Predicate<Person>(filter.FilterByLastName);    35             //List<Person> list = personList.FindAll(filterByLastName);    36     37             //Response.Write("Original Collection Count " + personList.Count.ToString() + "<br />");    38             //Response.Write("Filtered List Count " + list.Count.ToString() + "<br />");    39     40             //// this is a shorter version and uses the RemoveAll method to items    41             //personList.RemoveAll(filterByLastName);    42             //Response.Write("After persons removed from the collection Count " + personList.Count.ToString());    43     44             //Sample 2 shortform version    45             List<Person> list2 = personList.FindAll(new PersonFilter("Rose").FilterByLastName);    46             Response.Write("Count " + list2.Count.ToString());   47     48     49             //Sample 3 using lambda expression    50             //List<Person> list3 = personList.FindAll(    51             //    r => r.LastName == "Rose");    52             //Response.Write("Count " + list3.Count.ToString());   53     54     55             //Sample 4 with arrays    56             //Person[] personList2 = {    57             //   new Person("Rose", "Bob"),    58             //   new Person("Rose", "Phil"),    59             //   new Person("Smith", "Jack"),    60             //};    61             //outputs each person in array    62             //Array.ForEach(personList2, delegate(Person p)    63             //{    64             //    Response.Write(p.LastName + "<br />");    65             //});    66     67             //outputs each person after findall    68             //Person[] personList3 = Array.FindAll(personList2,    69             //    delegate (Person p)    70             //    {    71             //        return p.LastName == "Rose";    72             //    }    73             //);    74             //Array.ForEach(personList3, delegate(Person p)    75             //{    76             //    Response.Write(p.LastName + "<br />");    77             //});
The following are simple classes used in the above exmaples
   86     public class Persons : System.Collections.Generic.List<Person> {    87     88     public Persons() {    89     }    90 }    91     92     93     94 public class Person {    95     96     private string _lastName;    97     private string _firstName;    98     public string LastName {    99         get {   100             return _lastName;   101         }   102         set {   103             _lastName = value;   104         }   105     }      106     public string FirstName {   107         get {   108             return _firstName;   109         }   110         set {   111             _firstName = value;   112         }   113     }   114    115     public Person(string lastName, string firstName) {   116         _lastName = lastName;   117         _firstName = firstName;   118     }      119    120 }   121    122    123 public class PersonFilter   124 {   125    126     private string _match;   127    128     public PersonFilter(string match)   129     {   130         _match = match;   131     }   132    133     public bool FilterByLastName(Person per)   134     {   135         if (per.LastName == _match)   136         {   137             return true;   138         }   139         return false;   140     }   141    142    143     public bool FilterByFirstName(Person per)   144     {   145         if (per.FirstName == _match)   146         {   147             return true;   148         }   149         return false;   150     }   151 }