TopN in Linq


This post is a short on the power of LINQ. Particularly how to get a TopN from LINQ easily.

I had the idea of including in the run summary for a piece of software I’ve been developing at work the TopN sized tables loaded, or TopN elapse times (there will be a couple of posts on this subject in the coming days). This software is using the SqlBulkCopy to load data into a Sql Server 2008 database. It’s a bit special, in that it has the following features:

  • loads each table on separate parallel thread (using the ThreadPool class) (I’ll think about using .Net 4.0 Task sometime),
  • implements the IDataReader over a tab delimited file which has the column names for the data as the first line (a header row),
  • extracts the data files from ZIP archive (this is on different threads for each of the ZIP files being processed) using the Ionic DotNet Zip Library,
  • creates the Table to load the data into, on the fly (along with the Database, and Schemas in the database),
  • uses the Enterprise Library Logging facilities (a simple rolling flat file at present – I’ll get on to using the write to a database table for logging part one day),

Anyway, I’ll post some fragments from project this over then next couple of days (or maybe a bit longer).

Back to the TopN using Linq. I think I’ll let the code speak for itself (plus a couple of strategic comments).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace LinqTopNDemo
{
    /// <summary>
    /// A simple little class which has the demo data
    /// </summary>
    internal class DemoData
    {
        /// <summary>
        /// The demo name (no imagination here)
        /// </summary>
        public string Name;
        /// <summary>
        /// An integer value to do some TopN on
        /// </summary>
        public int Salary;
        /// <summary>
        /// A date filed which is also used for TopN'ing 
        /// (just to show this works for more than numbers
        /// </summary>
        public DateTime BirthDay;
        /// <summary>
        /// A quick constructor for the data holder class
        /// </summary>
        /// <param name="name"></param>
        /// <param name="salary"></param>
        /// <param name="birthday"></param>
        public DemoData(string name, int salary, DateTime birthday)
        {
            this.Name = name;
            this.Salary = salary;
            this.BirthDay = birthday;
        }
        /// <summary>
        /// Overload of ToString to spit out the values 
        /// Makes the demo code easier
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            StringBuilder retVal = new StringBuilder();
            retVal.AppendFormat("Name = {0}, Salary = {1}, Birthday = {2}", 
                this.Name, this.Salary, this.BirthDay.ToLongDateString());
            return retVal.ToString();
        }
    }
    /// <summary>
    /// The main of the program
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            List<DemoData> demo = new List<DemoData>();
            PopulateDemoData(demo);
            // get the top 2 salaries
            var top2Salaries = demo.OrderByDescending(a => a.Salary).Take(2);
            Debug.WriteLine("Top 2 Salaries");
            foreach (var a in top2Salaries)
                Debug.WriteLine(a);
            // get the top 2 birth dates
            var top2Dates = demo.OrderByDescending(a => a.BirthDay).Take(2);
            Debug.WriteLine("Top2 Birthdates");
            foreach (var a in top2Dates)
                Debug.WriteLine(a);
        }

        /*
         * 
         * Output: 
Top 2 Salaries
Name = Jane Doe, Salary = 15678, Birthday = Sunday, 1 June 1980
Name = John Doe, Salary = 10000, Birthday = Thursday, 31 January 1991
Top2 Birthdates
Name = Fred Nerk, Salary = 2, Birthday = Saturday, 1 December 2001
Name = John Doe, Salary = 10000, Birthday = Thursday, 31 January 1991
         */

        /// <summary>
        /// Just populate the list with some dummy people.
        /// </summary>
        /// <param name="demo"></param>
        private static void PopulateDemoData(List<DemoData> demo)
        {
            demo.Add(new DemoData("Fred Nerk", 2, DateTime.Parse("2001-12-01")));
            demo.Add(new DemoData("John Doe", 10000, DateTime.Parse("1991-01-31")));
            demo.Add(new DemoData("Jane Doe", 15678, DateTime.Parse("1980-06-01")));
        }
    }
}
del.icio.us Tags: ,,,
Digg This
Advertisements

, ,

  1. Leave a comment

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: