Generic Collections and Filtering

posted on Saturday, September 13, 2008 8:51 AM

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 }

category: .NET Language Features

Comments


# re: Generic Collections and Filtering
Posted by Jeff Handley on 9/14/2008 12:58 AM
Gravatar Look at your writing C# :-)

I am liking the lambda approaches more and more myself.
Post Comment
Title *
Name *
Email
Url
Comment *
Please add 8 and 4 and type the answer here:

About Me

An engineer by training and a software developer at heart. My techniques and approaches meld engineering approaches with software technology.

Core to these principles is a systematic approach to the development of software with a strong lifecycle and process management emphasis through adoption of mature technologies.

Ten years designing heavy structural steel and concrete structures and 12 years in the software development profession have embedded strong project management and business knowledge in my approaches.

Subscribe to Rss Feed


Follow me on twitter @dyardy