Re.Mark

My Life As A Blog

LINQed Lists

with 2 comments

While working on the National Rail Enquiries Proof of Concept, I needed to be able to filter a list of data.  Before the advent of LINQ that meant writing a heap of code – for the sake of context it’s worth noting that the list is held in memory as a list and is originally populated from an XML file.  LINQ works just as well against lists as it does against data. Let’s say we wanted to extract all numbers that contained an e.  Here’s how you could do it with LINQ:

List<string> stringList = new List<string>(new string[] { "one", "two", "three", "four", 
                                 "five", "six", "seven", "eight", "nine", "ten" });

foreach (string result in (from item in stringList
                           where item.Contains('e')
                           select item))
{
    Console.WriteLine(result);
}

The letter could be passed in as an argument to a function, to make the query more dynamic.  In fact we could run even call a function from within the query.  An example would be to test if a string matched a regular expression.  Here’s a simple function that does exactly that:

private static IList<string> Matches(string text)
{
    List<string> stringList = new List<string>(new string[] { "one", "two", "three", "four",
                                      "five", "six", "seven", "eight", "nine", "ten" });

    return (from item in stringList
            where Regex.IsMatch(item, text)
            select item).ToList<string>();
}

Let’s try and do something a little more complicated (only a little, mind.)  Here’s a simple Person class:

class Person
{
    public string Name { get; private set; }
    public DateTime Birthdate { get; private set; }

    public Person(string name, DateTime birthdate)
    {
        this.Name = name;
        this.Birthdate = birthdate;
    }

    public int Age
    {
        get
        {
            return DateTime.Now.Year - this.Birthdate.Year;
        }
    }

    public override string ToString()
    {
        return string.Format("{0} - {1}", this.Name, this.Age);
    }
}

To give something to work against, here’s a Populate function that’ll fill a list with Person objects:

private static void PopulateList(IList<Person> people)
{
    people.Add(new Person("Fred", DateTime.Parse("1/1/1934")));
    people.Add(new Person("Fred", DateTime.Parse("1/1/1984")));
    people.Add(new Person("Fred", DateTime.Parse("1/1/1978")));
    people.Add(new Person("Fred", DateTime.Parse("1/1/1966")));
    people.Add(new Person("George", DateTime.Parse("1/1/1937")));
    people.Add(new Person("George", DateTime.Parse("1/1/1996")));
    people.Add(new Person("Edna", DateTime.Parse("1/1/2001")));
    people.Add(new Person("Edna", DateTime.Parse("1/1/1954")));
}

OK – we want to get a list of all people with a given name over a given age and order the results by age.  Here’s a function to do that:

private static void PeopleOverGivenAgeWithGivenName(int age, string name)
{
    List<Person> people = new List<Person>();
    PopulateList(people);

    foreach (Person person in (from item in people
                               where (item.Age > age) && (item.Name.CompareTo(name) == 0)
                               orderby item.Age
                               select item))
    {
        Console.WriteLine(person);
    }
}

Of course, you might also want to get a particular item – let’s say for instance that the Person class had a National Insurance number property.  We could find the person with a given National Insurance number with the following code:

private static Person GetPersonByNationalInsuranceNumber(string nationalInsuranceNumber)
{
    List<Person> people = new List<Person>();
    PopulateList(people);

    return (from item in people
            where (item.NationalInsuranceNumber.CompareTo(nationalInsuranceNumber) == 0)
            select item).Single();
}

I used LINQ to filter lists and select items from list when writing the mobile phone application, LINQ is part of the .NET Compact Framework 3.5 – just make sure you have a reference to System.Core.  It saved me a lot of code and I find that the LINQ code is a lot easier to read.

Advertisements

Written by remark

October 6, 2008 at 5:48 pm

2 Responses

Subscribe to comments with RSS.

  1. Also its worth noting that it’s also sometimes easier to just use the extension methods and lambda’s that LINQ is based upon, e.g:

    var stringList = new[] { “one”, “two”, “three”, “four”, “five”,
    “six”, “seven”, “eight”, “nine”, “ten” }.ToList();

    stringList.FindAll(item => item.Contains(‘e’)).ForEach(item =>Console.WriteLine(item));

    foreach (var person in people.FindAll(x => x.Age > age && x.Name == name).OrderBy(x => x.Age)) {
    Console.WriteLine(person);
    }

    var person = people.Single(p => p. NationalInsuranceNumber == nin);

    Demis

    October 7, 2008 at 12:33 am

  2. Demis,

    Thanks for the extra detail. Personally, I like the conciseness of the lambda expressions, but I find them a little more difficult to read. Good to see more examples of using LINQ.

    remark

    October 13, 2008 at 9:36 pm


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: