471,578 Members | 1,455 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,578 software developers and data experts.

Searching ArrayList of Classes

I've got arraylists of simple classes bound to controls. I need to search
through those arraylists to set the correct SelectedItem in the control.
The code looks like:

Public Class DegreeMaintenance
Private arrCipCodes As New ArrayList
'populate reader with data
With rdr
Do While .Read
arrCipCodes.Add(New CipCode(.GetString(0), .GetString(1)))
Loop
.Close()
End With
arrCipCodes.Sort()

Public ReadOnly Property CipCodes() As ArrayList
Get
Return arrCipCodes
End Get
End Property
End Class
'************************************************* ****************
Public Class CipCode
Private myCipDisplay As String
Private myCipCode As String
Public Sub New(ByVal strCipDisplay As String, ByVal strCipCode As
String)
MyBase.new()
With Me
.myCipDisplay = strCipDisplay 'e.g. 01.9999 Agriculture,
Agriculture Operations and Related Sciences, Other
.myCipCode = strCipCode 'e.g. 01.9999
End With
End Sub
Public ReadOnly Property CipDisplay() As String
Get
Return myCipDisplay
End Get
End Property
Public ReadOnly Property CipCode() As String
Get
Return myCipCode
End Get
End Property
End Class
'************************************************* ***************
And finally in a form is this code:
'
Me.cbCipCode.SelectedIndex =
DegreeMaintenance.CipCodes.BinarySearch(dd.CipDisp lay)

When I execute this line I get this message:
Additional information: Specified IComparer threw an exception.

I'm not sure where to go from here. Do I need to implement an IComparer?
How do I search on the second element of the class members of my arraylist?

Nov 21 '05 #1
9 2752
Paul Nations wrote:
I've got arraylists of simple classes bound to controls. I need to search through those arraylists to set the correct SelectedItem in the control. The code looks like:

Public Class DegreeMaintenance
Private arrCipCodes As New ArrayList
'populate reader with data
With rdr
Do While .Read
arrCipCodes.Add(New CipCode(.GetString(0), ..GetString(1))) Loop
.Close()
End With
arrCipCodes.Sort()

Public ReadOnly Property CipCodes() As ArrayList
Get
Return arrCipCodes
End Get
End Property
End Class
'************************************************* ****************
Public Class CipCode
Private myCipDisplay As String
Private myCipCode As String
Public Sub New(ByVal strCipDisplay As String, ByVal strCipCode As
String)
MyBase.new()
With Me
.myCipDisplay = strCipDisplay 'e.g. 01.9999 Agriculture, Agriculture Operations and Related Sciences, Other
.myCipCode = strCipCode 'e.g. 01.9999
End With
End Sub
Public ReadOnly Property CipDisplay() As String
Get
Return myCipDisplay
End Get
End Property
Public ReadOnly Property CipCode() As String
Get
Return myCipCode
End Get
End Property
End Class
'************************************************* ***************
And finally in a form is this code:
'
Me.cbCipCode.SelectedIndex =
DegreeMaintenance.CipCodes.BinarySearch(dd.CipDisp lay)

When I execute this line I get this message:
Additional information: Specified IComparer threw an exception.

I'm not sure where to go from here. Do I need to implement an IComparer?

Yes. BinarySearch needs to be able to compare the objects in the
ArrayList in order to search it, and it doesn't know how to compare
CipCode's.
How do I search on the second element of the class members of my

arraylist?

TWO WAYS to do this:

a) First method: Define a class that compares CipCode's and implements
IComparer; supply one of these to BinarySearch:

Public Class CipCodeComparer
Implements IComparer

Public Function Compare(ByVal x As Object, ByVal y As Object) As
Integer Implements System.Collections.IComparer.Compare
'because we don't type check here -
'it becomes our responsibility to ensure that a CipCodeComparer
'is only ever used to compare CipCode's
Dim cx As CipCode = DirectCast(x, CipCode)
Dim cy As CipCode = DirectCast(y, CipCode)

Return String.Compare(cx.CipCode, cy.CipCode)

End Function
End Class

Hopefully this will be self-explanatory - this is a class whose sole
purpose is to provide an implementation of IComparer that compares
CipCode's by their CipCode property. Note that I have taken the
stylistic decision to explicitly passthrough to String.Compare; I could
just as easily have said

if cx.cipcode < cy.cipcode then
return -1
elseif cx.cipcode > cy.cipcode then
return 1
else
return 0
end if

I think just passing through to String.Compare better shows what is
being done.

Anyway, once you've defined this class, you just need to supply it to
BinarySearch using the appropriate overload:

Me.cbCipCode.SelectedIndex =
DegreeMaintenance.CipCodes.BinarySearch(dd.CipDisp lay, New
CipCodeComparer)

and you should be in business.

b) Second method: have CipCode implement IComparable, so that when the
default comparer (the one that gets used when no comparer is explicitly
mentioned in the call to BinarySearch) comes calling, comparisons will
be done as you want:

add to the definition of CipCode:
Implements IComparable

Public Function CompareTo(ByVal obj As Object) As Integer
Implements System.IComparable.CompareTo
Dim other As CipCode = DirectCast(obj, CipCode)
Return Me.CipCode.CompareTo(other.CipCode)
End Function

(as before, without type checking it's our responsibility to make sure
CipCode's are only ever compared to other CipCode's)

Now when you use the comparer-less overlod of BinarySearch, it will
know get a useful answer when it asks the CipCode's to compare amongst
themselves.

btw, be sure to check you're filling the ArrayList in Code order, as
BinarySearch assumes this.
--
Larry Lard
Replies to group please

Nov 21 '05 #2
Larry;

I really appreciate the help. It's what I was trying to do before I got
desperate and posted to the newsgroup.

However, I've tried both methods you suggested and am still getting the
"Specified IComparer threw an exception." error.

I've put a break in the compare functions of both methods and the
execution never enters that function.

Reading the newsgroups, I read that I should be able to set a break in
the compare fns and see the code executing in there, but I never get
that far.

Thanks for any further consideration you can give to this.

*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
Nov 21 '05 #3

OK will look again later but just quickly to check that when you
implement IComparer, you are actually passing an instance to
BinarySearch? eg

Me.cbCipCode.SelectedIndex =
DegreeMaintenance.CipCodes.BinarySearch(dd.CipDisp lay, New MyComparer)

Just checking the obvious stuff first :)
Paul Nations wrote:
Larry;

I really appreciate the help. It's what I was trying to do before I got desperate and posted to the newsgroup.

However, I've tried both methods you suggested and am still getting the "Specified IComparer threw an exception." error.

I've put a break in the compare functions of both methods and the
execution never enters that function.

Reading the newsgroups, I read that I should be able to set a break in the compare fns and see the code executing in there, but I never get
that far.

Thanks for any further consideration you can give to this.

*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!


Nov 21 '05 #4
Yes. Here's the line:

Me.cbCipCode.SelectedIndex =
cDegreeMaintenance.CipCodes.BinarySearch(dd.CipDis play, New
CipCodeComparer)

Does the CipCodeComparer class need a Public Sub New or something
besides the Implements & Compare function? How does it get
instantiated?

*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
Nov 21 '05 #5
In all the examples from Dynamic Help where a comparer is built, the
comparer class is embedded within another class. Is this necessary? Can
the comparer class be a standalone? If not where would I embed the comparer
class, in the class of objects being compared or in the form calling the
comparison?

Thanks.

"Paul Nations" <pa***@adhe.arknet.edu> wrote in message
news:eU*************@TK2MSFTNGP15.phx.gbl...
Yes. Here's the line:

Me.cbCipCode.SelectedIndex =
cDegreeMaintenance.CipCodes.BinarySearch(dd.CipDis play, New
CipCodeComparer)

Does the CipCodeComparer class need a Public Sub New or something
besides the Implements & Compare function? How does it get
instantiated?

*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!

Nov 21 '05 #6

Sorry for not coming back Paul.

You don't need to explicitly code a constructor for your comparer class
- remember that when you don't provide a constructor, VB implicitly
creates a 'null' constructor (that takes no arguments and does
nothing), so just doing New CipCodeComparer as you have is fine.

As to where to define the comparer, the general OO principle is that
you 'hide' it as much as you can, which is why examples often have
comparers defined as private (embedded) classes. If you're going to
have a comparer that is used across classes then you would need to
define it in a broader scope.

If you're still having trouble getting it to work, try stripping the
code down to a minimal not-working example then post that.
Paul Nations wrote:
In all the examples from Dynamic Help where a comparer is built, the
comparer class is embedded within another class. Is this necessary? Can the comparer class be a standalone? If not where would I embed the comparer class, in the class of objects being compared or in the form calling the comparison?

Thanks.

"Paul Nations" <pa***@adhe.arknet.edu> wrote in message
news:eU*************@TK2MSFTNGP15.phx.gbl...
Yes. Here's the line:

Me.cbCipCode.SelectedIndex =
cDegreeMaintenance.CipCodes.BinarySearch(dd.CipDis play, New
CipCodeComparer)

Does the CipCodeComparer class need a Public Sub New or something
besides the Implements & Compare function? How does it get
instantiated?

*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!


Nov 21 '05 #7
I've stripped out everything that doesn't relate to the BinarySearch
problem I'm having. The source is in 3 files plus the data xml.

Everything is here:
http://www.arkansashighered.com/soft...rchproblem.zip
*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
Nov 21 '05 #8

Paul Nations wrote:
I've stripped out everything that doesn't relate to the BinarySearch
problem I'm having. The source is in 3 files plus the data xml.

Everything is here:
http://www.arkansashighered.com/soft...rchproblem.zip


OK, what's happening is that you're actually searching the ArrayList of
CipCodes for a given CipCode based on the just the code, ie what you
want is:

Given the *code* and the collection, return the index of the object
with that code within the collection

whereas what BinarySearch does is

Given the *object* and the collection, return the index of that object
within that collection.
Probably the easiest way out of this is to note that when the main form
calls the edit for, at that point we *already* know the index of the
selected code within the list - so just make this one of the arguments
with which the edit form is created! - pass it through to
PopulateControls and set the combo box's index to it.
If you do later want the ability to get a CIP object given just the
code, look into using a Hashtable.

--
Larry Lard
Replies to group please

Nov 21 '05 #9
OK. That sounds reasonable. I'll try that, since I'm already passing
in some other values in the Sub New.

Thanks for all your efforts.

*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
Nov 21 '05 #10

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

3 posts views Thread by Pablo Salazar | last post: by
5 posts views Thread by Kevin | last post: by
2 posts views Thread by Chuck Bowling | last post: by
4 posts views Thread by Stuart | last post: by
10 posts views Thread by C Downey | last post: by
18 posts views Thread by Sam | last post: by
4 posts views Thread by MikeY | last post: by
reply views Thread by XIAOLAOHU | last post: by
reply views Thread by lumer26 | last post: by
reply views Thread by lumer26 | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.