It was lunch time was I was thinking of stepping out for a good lunch at Nando’s when a friend of mine sent me an email and he was taking about some issue he has come up with where in he has to order something . I said use generics . Well then I came across this puzzle on Eric’s blog (he is a Senior Dev in C# compiler team). The problem is mentioned here http://blogs.msdn.com/ericlippert/archive/2009/04/15/comma-quibbling.aspx
I decided to solve it and some how used generics , LINQ , Lambda expression and I thought my this blog can serve as a small pointer on how to use it in day to day programming. (For details on these please go to MSDN or somewhere else. This entry is just a demo of what these stuff look like and how can it be used in very simple terms)
So now the PROBLEM
Given a sequence of strings, concatenate them in a way similar to natural language. For example the sequence "ABC", "DEF", "G", and "H" should be output as: {ABC, DEF, G and H} "ABC" and "DEF" should be output as… {ABC and DEF} and finally an empty sequence should yield the following output: {} . Now I am not going to handle the last bit that is the empty string part so just leave it.
So Here is the code (it is a console app and should work from VS 2008 onwards)
- using System;
- using System.Collections.Generic;
- using System.Collections;
- using System.Text;
- using System.Linq;
- namespace intrestingCSharpe
- {
- public class mySortedList
- {
- private string _str;
- public string Str
- {
- get { return _str; }
- set { _str = value; }
- }
- private int _pos;
- public int Pos
- {
- get { return _pos; }
- set { _pos = value; }
- }
- }
- public class Program
- {
- public static int retAsciOfFirst(char ch)
- {
- return Convert.ToInt32(ch);
- }
- static void Main(string[] args)
- {
- List<string> sort = new List<string>();
- sort.Add("ABC");
- sort.Add("G");
- sort.Add("DEF");
- sort.Add("H");
- List<mySortedList> sortedlist = new List<mySortedList>();
- foreach (string s in sort)
- {
- mySortedList sorted = new mySortedList();
- sorted.Str = s;
- sorted.Pos = Convert.ToInt32(s.ToCharArray().GetValue(0));
- sortedlist.Add(sorted);
- }
- IEnumerable<string> sortDescendingQuery =
- from s in sortedlist
- orderby s.Pos
- select s.Str ;
- string contcatenator; int count = sortDescendingQuery.Count(); int counter = 1;
- foreach (string s in sortDescendingQuery)
- {
- if(counter == 1)
- {
- contcatenator = "";
- Console.Write("{0}", "{"+contcatenator + s);
- }
- else if (counter > 1 && counter < count)
- {
- contcatenator = ",";
- Console.Write("{0}", contcatenator + s);
- }
- else if (counter == count)
- {
- contcatenator = " AND ";
- Console.Write("{0}", contcatenator + s+"}");
- }
- counter++;
- }
- Console.Read();
- }
- }
- }
So some explanation now. I created a class(type) mySortedList which has 2 properties str and pos and I am using this class as the generic type. Generic list<T> needs a type so I can use my class. Handy here as I can store a list of my class type and enumerate over the collection and so on.
Now I have written a small LINQ query as well to do the ordering. It does the job. but a even better way will be to use the lambda expression to order this List<mySorterList>().
IMPROVEMET 1 : I will use a delegate to the ordering and not created another list but rather order the same list
So Here is the code . Just Comment the LINQ query and replace it with the delegate code till the end
- sortedlist.Sort(delegate(mySortedList s1, mySortedList s2) { return s1.Pos.CompareTo(s2.Pos); });
- string contcatenator; int count = sortedlist.Count(); int counter = 1;
- foreach (mySortedList s in sortedlist)
- {
- if(counter == 1)
- {
- contcatenator = "";
- Console.Write("{0}", "{"+contcatenator + s.Str);
- }
- else if (counter > 1 && counter < count)
- {
- contcatenator = ",";
- Console.Write("{0}", contcatenator + s.Str);
- }
- else if (counter == count)
- {
- contcatenator = " AND ";
- Console.Write("{0}", contcatenator + s.Str + "}");
- }
- counter++;
- }
- Console.Read();
Nice. But as I can use delegate here why not use LAMBDA Expression instead.
Just a small syntax explanation . Lambda expression are a functional programming construct and has been added to C# 3.0. The way it is written is
Sqr X => X*X meaning a function Sqr is a function of X which “goes to” X*X
ok so lets replace the above ordering by using lambda expression. The code becomes
I can replace the delegate by this
- sortedlist.Sort((mySortedList p1, mySortedList p2) => p1.Pos.CompareTo(p2.Pos));
There are many other ways . I can use anonymous method to this sort return etc etc. So IN sort C#3.0 ‘s functional programming features like generics , LINQ , Lambda expressions , anonymous method are amazing . So do pay some attention to them to clean up your code written in frameworks 1.0 and 1.1 (2.0 has generics and anonymous method).
happy coding. and ya the output is (many other have used other way but I used ASCII encoding to have some more fun)
