|
|
Controlling Searches and Comparisons in .NET
|
|
|
|
Archive of Previous Articles
|
|
|
|
|
 |
|
|
Imports Microsoft.VisualBasic Imports System Imports System.Collections
Public Class SearchArray
Public Shared Sub Main() Dim sStates() As String = {"New York", _ "California", _ "Michigan", _ "Washington"} Dim sState As String Dim iResult As Integer
Array.Sort(sStates) sState = InputBox("Enter state name: ") iResult = Array.BinarySearch(sStates, sState) If iResult >= 0 Then Console.WriteLine(sState & _ " is at position " & _ iResult) Else If (Not iResult) = sStates.Length + 1 Then Console.WriteLine(sState & " not found.") Else Console.WriteLine("Nearest match to " & _ sState & " at position " & not iResult) End If End If End Sub End Class
|
|
|
|
Public Shared Function BinarySearch(ByVal array As Array, _ ByVal value As Object _ ) As Integer
|
|
|
|
Public Shared Function BinarySearch(ByVal array As Array, _ ByVal value As Object, _ ByVal comparer As IComparer _ ) As Integer
|
|
|
|
Imports Microsoft.VisualBasic Imports System Imports System.Collections
Public Class SearchArray Public Shared Sub Main() Dim cic As New CaseInsensitiveComparer Dim sStates() As String = {"New York", _ "California", _ "Michigan", _ "Washington"} Dim sState As String Dim iResult As Integer
Array.Sort(sStates) sState = InputBox("Enter state name: ") iResult = Array.BinarySearch(sStates, sState, cic) If iResult >= 0 Then Console.WriteLine(sState & " is at position " & iResult) Else If (Not iResult) = sStates.Length + 1 Then Console.WriteLine(sState & " not found.") Else Console.WriteLine("Nearest match to " & sState & _ " at position " & not iResult) End If End If End Sub End Class
|
|
|
|
Imports Microsoft.VisualBasic Imports System Imports System.Collections
Public Class Player Protected sName As String Protected sTeam As String Protected iYear As Integer Protected sngBA As Single
Public Sub New(name As String, team As String, _ year As Integer, ba As Single) sName = name sTeam = team iYear = year sngBA = ba End Sub
Public ReadOnly Property Name As String Get Return sName End Get End Property
Public ReadOnly Property Team As String Get Return sTeam End Get End Property
Public ReadOnly Property Year As Integer Get Return iYear End Get End Property
Public ReadOnly Property BA As Single Get Return sngBA End Get End Property End Class
Public Class CompareBA Implements IComparer
Public Function Compare(x As Object, y As Object) As Integer _ Implements IComparer.Compare
If TypeOf y Is Player Then If x.BA > y.BA Then Return 1 ElseIf x.BA < y.BA Then Return -1 Else Return 0 End If Else If x.BA > y Then Return 1 ElseIf x.BA < y Then Return -1 Else Return 0 End If End If End Function End Class
Public Class PlayerArray
Public Shared Sub Main() Dim Players(5) As Player Dim compBA As New CompareBA
Players(0) = New Player("Ty Cobb", "Det", 1910, .385) Players(1) = New Player("Willie Mays", "S.F.", 1963, .314) Players(2) = New Player("Cal Ripken", "Balt", 1983, .318) Players(3) = New Player("Ted Williams", "Bos", 1947, .342) Players(4) = New Player("Al Kaline", "Det", 1961, .324) Players(5) = New Player("Ted Williams", "Bos", 1941, .406) Array.Sort(Players, compBA)
For Each p As Player In Players Console.WriteLine(p.Name & " in " & p.Year & ": " & p.BA) Next
Dim BAIn As Single Dim SearchPos As Integer
BAIn = CSng(InputBox("Enter batting average to find: ")) SearchPos = Array.BinarySearch(Players, BAIn, compBA)
If SearchPos >= 0 Then Console.WriteLine("BA found at position " & SearchPos & _ ": " & Players(SearchPos).Name & _ " in " & Players(SearchPos).Year) Else SearchPos = (Not SearchPos) If SearchPos = Players.Length + 1 Then Console.WriteLine(BAIn & " not found.") Else Console.WriteLIne("Nearest average to " & BAIn & _ " is " & Players(SearchPos).Name & _ " in " & Players(SearchPos).Year) End If End If End Sub
End Class
|
|
|
|
Class
|
Member(s)
|
System.Array
|
BinarySearch, Sort
|
System.Collections.ArrayList
|
BinarySearch, Sort
|
System.collections.Hashtable
|
constructor
|
System.Collections.Specialized.ListDictionary
|
constructor
|
System.Collections.Specialised.NameObjectCollectionBase
|
constructor
|
System.Collections.Specialized.NameValueCollection
|
constructor
|
System.XML.XPath.XPathExpression
|
AddSort
|
System.ComponentModel.EventDescriptorCollection
|
InternalSort, Sort
|
System.ComponentModel.PropertyDescriptorCollection
|
InternalSort, Sort
|
System.Collections.SortedList
|
constructor
|
System.Windows.Forms.ListView
|
ListViewItemSorter
|
System.ComponentModel.EnumConverter
|
Comparer
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|





Howling Wolf Consulting Services
In Visual Basic 6.0 and earlier versions, string comparisons were controlled by
the Option Compare statement located at the top of a particular class,
form, or code module. If set to Text, comparisons were case insensitive. As
a result, code such as
str1 = "string"
str2 = "STRING"
MsgBox str1 = str2
returns True. When the setting is changed to Binary, the string comparison
returns False. This setting controls all string comparisons and cannot be
changed within a procedure. However, it does not affect the Item property of
a Visual Basic Collection object, which always performs a case-
insensitive comparison. In addition, the Dictionary class in the Microsoft
Scripting Runtime Library (scrrun.dll) has a ComnpareMode property that
allows you to determine whether a comparison of dictionary keys is case
sensitive or insensitive.
Visual Basic .NET preserves the Option Compare statement, which
functions much like it did in previous versions of Visual Basic. However, for
some of the collection-like classes in the .NET Framework, it adds
considerable flexibility by allowing matching and searching to be customized.
In many cases when working with collections and arrays, you may not need to
do anything. By default, comparisons are case sensitive. So if you run the
following code and enter the string “new york” in the input box, a match will
not be found in the array, whereas a match will be found if you enter the string
“New York”:
To support some other comparison or sort method, you have to supply an
object that implements the IComparer interface as an argument to the
Array object’s BinarySearch method. (A class implementing
IComparer also can be used to determine the methods for sorting and
comparison for other classes, as the table at the end of this article shows, as
well as for sorting an array.) The syntax of this version of the Sort method
then changes from:
to
To make things easy, though, the .NET Framework supplies two classes --
Comparer and CaseInsensitiveComparer -- that implement the
IComparer interface and therefore allow you to change the search and
comparison method automatically. The Comparer class, in fact, is the default
IComparer implementation if no other is explicitly provided and supports
case-sensitive searches and sorts. Because of these predefined classes,
changing our example to implement a case-insensitive search for a key is very
easy, as the following code shows:
Regardless of whether we enter “New York” or “new york” (or some other
combination of upper- and lower-case letters) in the input box, the routine will
display the position of the New York element in the array.
But we can also implement our own custom search and sort criteria. The
IComparer interface has a single member, Compare. This method takes
two parameters of type Object, x and y, and returns an Integer indicating
the relationship of x to y. If x is greater than y (or if x is to follow y), it returns
a positive integer; if x is less than y (or if x is to precede y), it returns a negative
integer; and if the arguments are equal, it returns 0.
For example, let’s imagine that we have an object that represents a baseball
player’s batting average in a particular year. As the following code shows, we
can assign each player’s statistics to an element in the Players array:
The CompareBA class is then responsible for sorting the elements in the
order of the batting average, from lowest batting average to highest. We could
easily reverse the sort order by having CompareBA.Compare return a -1
if x.BA > y.BA and a 1 if y.BA > x.BA.
Although in our examples we have used classes implementing the
IComparer interface only with arrays, implementations of IComparer
can be used to control searching and sorting for a number of classes, including
the following: