A few weeks ago I wrote an article on how to use IComparer and how it was easy it is to create a custom comparer to sort our objects. This time we'll talk creating a default sort mechanism for our objects by using IComparer's relative, the interface IComparable. We'll also be touching Anonymous Delegates a bit.
I don't want to discuss the technical detail as I want to because it might bore the reader of this article, in turn i'll just be showing the code and some relative examples :). Also, we'll start with the same flow on how we demonstrated the last sample. I think story telling can be used effectively to demonstrate programming problems(much like code puzzles in college). Enough with the intro and back to code.
Our story starts with Rolvin. Rolvin is software engineer in the business district of Makati, a huge IT hub in the Philippines. Rolvin works hard usually doesn't go to lunch.. but when he does expect him to go around the block to check out girls in the restaurants and food courts around his office. One day while sitting at a popular burger shop an idea popped into Rolvin's mind. He realized that he is already 24, never had a girlfriend in his life and he thought to himself that it's about time for him to go out and date somebody. He closed his eyes for a second and had this wonderful bliss striking his mind. He said "I'll date the girls I've met around this joint!".
But our hero has a problem. He doesnt know who to date.
He has seen alot of girls around the area, met and chatted with some of them, got their numbers but he never thought about courting or asking some for a date up until now. Rolvin is smart.. he decided to pullout a tissue paper and listed all the names of the girls he met and some basic information about them. There are 3 things that he thought were important. First, the girl should have a name. Second, the girl that he will down on his list should have an age. And lastly, the "cuteness factor". He thinks that he is a very handsome guy and he deserves somebody equal or greater than his looks(talk about ego;)).
Ok, now this is our chance to help Rolvin. We need to create the Girl class first.
The Girl from Rolvin's definition should have a Name, Age and Cuteness Factor. The Girl class should also implement IComparable because we need have pre-defined sort mechanism in our class. Making a class inherit from IComparable is like giving the class the ability of "self-conciousness" wherein a class can decided whether it is greater or less than other classes. The listing below shows how the class would look like without the implementation of the sort inside the CompareTo Method.
[CODE: Girl.cs]
using System;
using System.Collections.Generic;
using System.Text;
namespace RolvinsGirlSelector
{
class Girl: IComparable<Girl>
{
private string _name;
private int _age;
private int _cutenessFactor;
/// <summary>
/// The name of the girl.
/// </summary>
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
/// <summary>
/// The age of the girl.
/// </summary>
public int Age
{
get
{
return _age;
}
set
{
_age = value;
}
}
/// <summary>
/// A "Rolvin" defined scaling factor that is from 0 to 5.
/// 0 being the lowest(not that appealing) and 5 being the highest(hot. extremely his type).
/// </summary>
public int CutenessFactor
{
get
{
return _cutenessFactor;
}
set
{
_cutenessFactor = value;
}
}
public Girl() { }
public Girl(string name, int age, int cutenessFactor)
{
this._name = name;
this._age = age;
this._cutenessFactor = cutenessFactor;
}
#region IComparable<Girl> Members
public int CompareTo(Girl other)
{
throw new Exception("The method or operation is not yet implemented.");
}
#endregion
}
}
Rolvin decided that the name doesn't matter to him. All he is concerned of is that the girl's age, availability and cuteness factor. The name is only there for him to serve as an identifier. Rolvin thinks about the names and information of the girls he met and listed each and everyone one of them.
[CODE: Program.cs]
using System;
using System.Collections.Generic;
using System.Text;
namespace RolvinsGirlSelector
{
class Program
{
static void Main(string[] args)
{
//A list of girls Rolvin would love to date
List<Girl> girls = new List<Girl>();
girls.Add(new Girl("Joan", 18, 4));
girls.Add(new Girl("Kristine", 19, 3));
girls.Add(new Girl("Maria", 18, 2));
girls.Add(new Girl("Luisa", 20, 2));
girls.Add(new Girl("Heart", 21, 5));
girls.Add(new Girl("Lynn", 20, 4));
girls.Add(new Girl("Phoebe", 22, 4));
girls.Add(new Girl("Anna", 23, 5));
girls.Add(new Girl("Allysa", 22, 5));
girls.Add(new Girl("Connie", 18, 5));
girls.Add(new Girl("May", 20, 5));
girls.Add(new Girl("Iyah", 24, 3));
girls.Add(new Girl("Rapunzel", 24, 5));
foreach (Girl g in girls)
{
Console.WriteLine("{0,-10} {1, -5} {2}", g.Name, g.Age, g.CutenessFactor);
}
Console.ReadLine();
}
}
}
/*Result
Joan 18 4
Kristine 19 3
Maria 18 2
Luisa 20 2
Heart 21 5
Lynn 20 4
Phoebe 22 4
Anna 23 5
Allysa 22 5
Connie 18 5
May 20 5
Iyah 24 3
Rapunzel 24 5
*/
Now that a list is created, Rolvin needs to decide on the criteria for the ranking. He closed his eyes once again and after a few seconds decided that he wants to sort the girls first by their cuteness factor.
[Modified CompareTo in Girls.cs]
#region IComparable<Girl> Members
public int CompareTo(Girl other)
{
return other.CutenessFactor.CompareTo(this.CutenessFactor);
}
#endregion
Looking at the list again after adding the line
girls.Sort();
Before calling the print code resulted to this
/*Result
Allysa 22 5
Heart 21 5
Anna 23 5
Rapunzel 24 5
May 20 5
Connie 18 5
Phoebe 22 4
Joan 18 4
Lynn 20 4
Kristine 19 3
Iyah 24 3
Luisa 20 2
Maria 18 2
*/
Now he knows who likes the most among the 13 girls that he selected.. but, there is a tie amongst the girls and he is still undecided on who to ask for a date. He looked at the list again and said to himself that he wants to date someone who is closer to his age. With that he modified his sorting criteria by adding the age to the criteria.
[Modified CompareTo in Girls.cs]
#region IComparable<Girl> Members
public int CompareTo(Girl other)
{
/* LEGEND
* < 0 means that this object is less than other
* 0 means that both objects are equal
* > 0 means that this object is greater than other
* */
int returnValue = -1;
if (other.CutenessFactor > this.CutenessFactor)
{
returnValue = 0;
}
else if (other.CutenessFactor == this.CutenessFactor)
{
returnValue = other.Age.CompareTo(this.Age);
}
return returnValue;
}
#endregion
Looking at the code again the result was this list
/*Result
Rapunzel 24 5
Anna 23 5
Allysa 22 5
May 20 5
Connie 18 5
Phoebe 22 4
Iyah 24 3
Kristine 19 3
Luisa 20 2
Joan 18 4
Heart 21 5
Lynn 20 4
Maria 18 2
*/
He now knows that Rapunzel is the first girl that she would ask out... He saw his friend Modchip and told him about his plans. To his amazement Modchip was also thinking of courting somebody.. Modchip the heartrob also has his own list which is surprisingly the same as what Rolvin have.. with one difference. Modchip rated the girls the same on the cuteness factor but he preffers the younger girls(OMG).
This time instead of using the CompareTo Method we will use an anonymous delegate to re-wire the sort method. After all, we don't want to modify the default comparer.
[Modified Sort Method with Anonymous Delegate]
girls.Sort(
delegate(Girl g1, Girl g2)
{
int returnValue = -1;
if (g2.CutenessFactor > g1.CutenessFactor)
{
returnValue = 0;
}
else if (g2.CutenessFactor == g1.CutenessFactor)
{
//descending
returnValue = g1.Age.CompareTo(g2.Age);
}
return returnValue;
}
);
Then they compared their list:
/*Result
Rolvin's Selection
Rapunzel 24 5
Anna 23 5
Allysa 22 5
May 20 5
Connie 18 5
Phoebe 22 4
Iyah 24 3
Kristine 19 3
Luisa 20 2
Joan 18 4
Heart 21 5
Lynn 20 4
Maria 18 2
-----
Modchip's Selection
Connie 18 5
May 20 5
Heart 21 5
Allysa 22 5
Anna 23 5
Rapunzel 24 5
Joan 18 4
Lynn 20 4
Phoebe 22 4
Kristine 19 3
Iyah 24 3
Maria 18 2
Luisa 20 2
*/
Sweet! Now they can start the dating process :) And Rolvin lived happily single after. LOL!
Hope you learned something out of this article. Thanks!
Posted
03-23-2007 11:59 AM
by
keithrull