When creating a custom data type; structure or class; if it is stored in an array of ArrayList, you can use the Array.BinarySearch and ArrayList.BinarySearch methods to do a custom searching of the data type in the array. This can be done by implementing the IComparable and/or IComparer interfaces.
By implementing the IComparable interface on your class (or structure), you can take advantage of the search routines of the Array, ArrayList, and SortedList classes. The algorithms for searching are built into these classes; all you have to do is tell them how to search through your classes via the code you implement in the IComparable.CompareTo method. The following class, Square, implements this interface:
public class Square : IComparable { public Square(){} public Square(int height, int width) { this.height = height; this.width = width; } private int height; private int width; public int Height { get { return (height); } set { height = value; } } public int Width { get { return (width); } set { width = value; } } public int CompareTo(object obj) { if (this.GetType() != obj.GetType()) { throw (new ArgumentException( "Both objects being compared must be of type Square.")); } else { Square square2 = (Square)obj; long area1 = this.Height * this.Width; long area2 = square2.Height * square2.Width; if (area1 == area2) { return (0); } else if (area1 > area2) { return (1); } else if (area1 < area2) { return (-1); } else { return (-1); } } } public override string ToString() { return ("Height:" + height + " Width:" + width); } }
IComparer is designed to solve the problem of allowing objects to be sorted based on different criteria in different contexts. This interface also allows us to sort types that we did not write. If we wanted to also be able to sort the Square objects by height, we could create a new class called CompareHeight, which would also implement the IComparer interface:
public class CompareHeight : IComparer { public int Compare(object obj1, object obj2) { if (!(obj1 is Square) || !(obj2 is Square)) { throw (new ArgumentException("Both parameters must be of type Square.")); } else { Square square1 = (Square)obj1; Square square2 = (Square)obj2; if (square1.Height == square2.Height) { return (0); } else if (square1.Height > square2.Height) { return (1); } else if (square1.Height < square2.Height) { return (-1); } else { return (-1); } } } }
The Array and ArrayList classes provide a BinarySearch method to perform a search on the elements in that array. The elements are compared against an object passed to the BinarySearch method in the object parameter. The SortedList class does not have a BinarySearch method; instead, it has Contains, ContainsKey, and ContainsValue methods to perform a linear search when searching for values. This linear search uses the Equals method of the elements in the SortedList collection to do its work, the Compare and CompareTo methods do not have any effect on the operation of the linear search performed in the SortedList class, but they do have an effect on binary searches.
To perform an accurate search using the BinarySearch methods of the Array and ArrayList classes, you must first sort the Array or ArrayList using its Sort method. In addition, if you pass an IComparer interface to the BinarySearch method, you must also pass the same interface to the Sort method. Otherwise, the BinarySearch method might not be able to find the object you are looking for.
The following method shows how to use the Square and CompareHeight structures with the Array, ArrayList, and SortedList classes:
public static void TestSearch() { Square[] arrayOfSquares = new Square[4] {new Square(1,3), new Square(4,3), new Square(2,1), new Square(6,1)}; ArrayList arrayListOfSquares = new ArrayList(); arrayListOfSquares.Add(new Square(1,3)); arrayListOfSquares.Add(new Square(4,3)); arrayListOfSquares.Add(new Square(2,1)); arrayListOfSquares.Add(new Square(6,1)); IComparer HeightCompare = new CompareHeight(); // Test an ARRAY Console.WriteLine("ARRAY"); Console.WriteLine("Original array"); foreach (Square s in arrayOfSquares) { Console.WriteLine(s.ToString()); } Console.WriteLine(); Console.WriteLine("Sorted array using IComparer=HeightCompare"); Array.Sort(arrayOfSquares, HeightCompare); foreach (Square s in arrayOfSquares) { Console.WriteLine(s.ToString()); } Console.WriteLine(); Console.WriteLine("Search using IComparer=HeightCompare"); int found = Array.BinarySearch(arrayOfSquares, new Square(1,3), HeightCompare); Console.WriteLine("found (1,3): " + found); Console.WriteLine(); Console.WriteLine("Sorted array using IComparable"); Array.Sort(arrayOfSquares); foreach (Square s in arrayOfSquares) { Console.WriteLine(s.ToString()); } Console.WriteLine("Search using IComparable"); found = Array.BinarySearch(arrayOfSquares, new Square(6,1), null); // Use IComparable Console.WriteLine("found (6,1): " + found); // Test an ARRAYLIST Console.WriteLine(); Console.WriteLine(); Console.WriteLine("ARRAYLIST"); foreach (Square s in arrayListOfSquares) { Console.WriteLine(s.ToString()); } Console.WriteLine(); Console.WriteLine("Sorted ArrayList using IComparer=HeightCompare"); arrayListOfSquares.Sort(HeightCompare); foreach (Square s in arrayListOfSquares) { Console.WriteLine(s.ToString()); } Console.WriteLine( ); Console.WriteLine("Search using IComparer=HeightCompare"); found = arrayListOfSquares.BinarySearch(new Square(1,3), HeightCompare); Console.WriteLine("found (1,3): " + found); Console.WriteLine(); Console.WriteLine("Sorted ArrayList using IComparable"); arrayListOfSquares.Sort(); foreach (Square s in arrayListOfSquares) { Console.WriteLine(s.ToString()); } Console.WriteLine( ); Console.WriteLine("Search using IComparable"); found = arrayListOfSquares.BinarySearch(new Square(6,1), null); Console.WriteLine("found (6,1): " + found); // Test a SORTEDLIST SortedList SortedListOfSquares = new SortedList( ); SortedListOfSquares.Add(0, new Square(1,3)); SortedListOfSquares.Add(2, new Square(4,3)); SortedListOfSquares.Add(1, new Square(2,1)); SortedListOfSquares.Add(3, new Square(6,1)); Console.WriteLine(); Console.WriteLine(); Console.WriteLine("SORTEDLIST"); foreach (DictionaryEntry s in SortedListOfSquares) { Console.WriteLine(s.Key + " : " + ((Square)s.Value).ToString()); } Console.WriteLine(); bool foundBool = SortedListOfSquares.Contains(2); Console.WriteLine("SortedListOfSquares.Contains(2): " + foundBool); foundBool = SortedListOfSquares.ContainsKey(2); Console.WriteLine("SortedListOfSquares.ContainsKey(2): " + foundBool); // Does not use IComparer or IComparable // -- uses a linear search along with the Equals method, which has not been // overloaded; if the Square object were to be used as the key // rather than the value, a binary search would be performed when searching // for this Square object. Square value = new Square(6,1); foundBool = SortedListOfSquares.ContainsValue(value); Console.WriteLine ("SortedListOfSquares.ContainsValue(new Square(6,1)): " + foundBool); }
This code displays the following output:
ARRAY Original array Height:1 Width:3 Height:4 Width:3 Height:2 Width:1 Height:6 Width:1 Sorted array using IComparer=HeightCompare Height:1 Width:3 Height:2 Width:1 Height:4 Width:3 Height:6 Width:1 Search using IComparer=HeightCompare found (1,3): 0 Sorted array using IComparable Height:2 Width:1 Height:1 Width:3 Height:6 Width:1 Height:4 Width:3 Search using IComparable found (6,1): 2 ARRAYLIST Height:1 Width:3 Height:4 Width:3 Height:2 Width:1 Height:6 Width:1 Sorted ArrayList using IComparer=HeightCompare Height:1 Width:3 Height:2 Width:1 Height:4 Width:3 Height:6 Width:1 Search using IComparer=HeightCompare found (1,3): 0 Sorted ArrayList using IComparable Height:2 Width:1 Height:1 Width:3 Height:6 Width:1 Height:4 Width:3 Search using IComparable found (6,1): 2 SORTEDLIST 0 : Height:1 Width:3 1 : Height:2 Width:1 2 : Height:4 Width:3 3 : Height:6 Width:1 SortedListOfSquares.Contains(2): True SortedListOfSquares.ContainsKey(2): True SortedListOfSquares.ContainsValue(new Square(6,1)): False
Popularity: 2% [?]
RSS feed for comments on this post · TrackBack URI
Leave a reply