Jump to content
Xtreme .Net Talk

Recommended Posts

Posted

Dear All,

 

 

I've been looking into the usage of the comparison interfaces over the past few days, as I need to sort and compare a particular class. My problem lies with the fact that, though I can compare the objects using the correct property, sorting requires the use of a different property.

 

As the data for the classes is directly taken from a database I compare the record's unique ID (SQL Server identity field) with either; the target equivalent class' id, or the specified integer. Each record also contains a SortOrder field, identifying its position in the list.

 

So, do I need to create an independent class to use as a comparer to sort my classes, or can I implement the interface within the current class but somehow trap what's needed to produce either a comparison or sort...

 

Alternatively, am I just losing the point somewhere?... :confused:

 

 

Paul.

Posted

the former... make an icomparer that compares the record id, another icomparer that comapres the class id and another that compares the sort order.

 

The reason why is, if you have a bunch of objects stored in an arraylist, you can just pass the icomparer instance to the arraylist.sort method.

Posted

I must be doing something wrong here. I've written the code and embedded it as a private class in my ICollection class...

...
...
   'Perform search for specific title in collection...
   Public Function GetCodeByName(ByVal pName As String) As sysCode
       Return itemArray(Array.BinarySearch(itemArray, compTitle))
   End Function
...
...
   'Comparer class for codes...
   Private Class CodeTitleComparer
       Implements IComparer

       'Compare function as implemented by the interface...
       Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements System.Collections.IComparer.Compare
           'Check that we're dealing with sysCode objects...
           If Not TypeOf x Is sysCode Or Not TypeOf y Is String Then
               Throw New InvalidCastException("Expected sysCode object")
           End If
           'Check the codes...
           Return String.Compare(CType(x, sysCode).Name, y.ToString)
       End Function

   End Class

The only trouble is that the BinarySearch result is always -17! Am I doing something wrong? Have I missed something?

 

 

Paul.

Posted
Do I need to sort the items, in that case, by whichever search I'm performing (i.e. if I'm doing a search on the title, the array needs to be sorted by the title etc)?
Posted

Ok, this is the code I've written to check for a particular title within the array of the current container class - it's fairly essential to the operation of the class...

Public Class sysCode
...
   Dim itemArray(15) As sysCode
...
   Private compId As New CodeIdComparer
   Private compTitle As New CodeTitleComparer
   Private compValue As New CodeValueComparer
...
   'Gets a child from the current collection...
   Public Function GetCodeByName(ByVal pName As String) As sysCode
       Array.Sort(itemArray, compTitle)
       Dim temp As Int32 = Array.BinarySearch(itemArray, pName, compTitle)
       Console.Write(temp)
   End Function
...
   'Comparer class for codes...
   Private Class CodeComparer
       Implements IComparer
       'Compare function as implemented by the interface...
       Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements System.Collections.IComparer.Compare
           'Check that we're dealing with sysCode objects...
           If Not TypeOf x Is sysCode Or Not TypeOf y Is sysCode Then
               Throw New InvalidCastException("Expected sysCode object")
           End If
           'Check the codes...
           Return CType(x, sysCode).Id.CompareTo(CType(y, sysCode).Id)
       End Function
   End Class
   'Comparer class for titles...
   Private Class CodeTitleComparer
       Implements IComparer
       'Compare function as implemented by the interface...
       Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements System.Collections.IComparer.Compare
           'Check that we're dealing with sysCode objects...
           If Not TypeOf x Is sysCode Or Not TypeOf y Is String Then
               Throw New InvalidCastException("Expected sysCode and String object")
           End If
           'Check the codes...
           Return String.Compare(CType(x, sysCode).Name, y.ToString)
       End Function
   End Class

End Class

The code above shows the basics for the search that I'm doing. For the sake of testing, I've replaced the actual return of the code object with a console.write of the returned value.

 

As you can see, the array gets sorted by the title, but still I'm getting a result of -17. I can't for the life of me see where it's going wrong! I feel I'm missing something basic....

 

If you can point out what's wrong I'd really appreciate it.

 

 

Many thanks,

Paul.

Posted

Im wondering...since itemArray is class scope...where do you initialize each object?

 

Anyhow, i don't see how it's sorting...

 

'Check that we're dealing with sysCode objects...
           If Not TypeOf x Is sysCode Or Not TypeOf y Is String Then
               Throw New InvalidCastException("Expected sysCode and String object")
           End If
           'Check the codes...
           Return String.Compare(CType(x, sysCode).Name, y.ToString)

 

You are checking for a sysCode object and a string. When sorting, you will only be getting syscode objects...

Posted

Yep - I was thinking about that this morning on the way to work, and realised that. I should be comparing the titles of two sysCode objects - I'm just off to try it now.

 

Many thanks Diesel,

 

Paul.

  • 4 weeks later...
Posted

My appologies for returning to this thread, but I've been away on holiday and now I'm back! Had a great time in Gran Canaria if you're interested, but anyway...

 

I've now moved on from the previous entry and have defined two classes for each search condition. The first sorts the class, the second allows a binary search given the appropriate type. But it's still not working - it's still returning a negative value. I've written separate classes now to deal with sorting and searching. Each one is applied in the appropriate command.

 

The code below belongs to a class called sysCode which provides a very useful look-up facility that allows multiple attributes for different codes. Originally I used a simple For...Next loop to loop through and obtain the searched for objects - a simple method so I could get the whole class working before I implemented more complex stuff. Now I'm looking at implementing IComparer, but just cannot get it to work!

Implements ICollection, IComparable
...
...
Private itemArray() As sysCode              'Accepts only code objects
Private arrayPointer As Integer = -1        'Pointer to the current object
Private arrayElements As Integer            'The number of elements in the array
Private defaultCollectSize As Integer = 16  'The default number of elements in the collection

Private sortId As New CodeIdSort
Private sortTitle As New CodeTitleSort
Private sortValue As New CodeValueSort
Private compId As New CodeIdComparer
Private compTitle As New CodeTitleComparer
Private compValue As New CodeValueComparer
...
...
'Compare...
Public Function CompareTo(ByVal obj As Object) As Integer Implements System.IComparable.CompareTo
   If TypeOf obj Is sysCode Then
       Return _Id.CompareTo(CType(obj, sysCode).Id)
   ElseIf TypeOf obj Is Int32 Then
       Return _Id.CompareTo(DirectCast(obj, Int32))
   ElseIf TypeOf obj Is String Then
       Return _Name.CompareTo(obj.ToString)
   Else
       Throw New InvalidCastException("sysCode, Int32, Integer, String or Date required.")
   End If
End Function
...
...
Public Function GetCodeByName(ByVal pName As String) As sysCode
   Dim tempId As Integer
   'There's no need to sort if we've only got 1 or less elements...
   If arrayPointer > 0 Then
       Array.Sort(itemArray, 0, arrayPointer, sortTitle)
       tempId = Array.BinarySearch(itemArray, 0, arrayPointer, pName, compTitle)
       If tempId >= 0 Then Return itemArray(tempId)
   End If
End Function
...
...
'Comparer class for titles...
Private Class CodeTitleSort
   Implements IComparer
   'Compare function as implemented by the interface...
   Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements System.Collections.IComparer.Compare
       'Check that we're dealing with sysCode objects...
       If Not TypeOf x Is sysCode Or Not TypeOf y Is sysCode Then
           Throw New InvalidCastException("Expected sysCode object")
       End If
       'Check the codes...
       Return DirectCast(x, sysCode).Name.CompareTo(DirectCast(y, sysCode).Name)
   End Function
End Class

'Comparer class for sorting titles...
Private Class CodeTitleComparer
   Implements IComparer
   'Compare function as implemented by the interface...
   Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements System.Collections.IComparer.Compare
       'Check that we're dealing with sysCode and string objects...
       If Not TypeOf x Is sysCode Or Not TypeOf y Is String Then
           Throw New InvalidCastException("Expected sysCode and String object")
       End If
       'Check the codes...
       Return String.Compare(DirectCast(x, sysCode).Name, y.ToString)
   End Function
End Class
...
...

As always - any pointers will be greatly appreciated.

 

 

Paul.

Posted

Debugging is a useful skill!

 

I recently had a problem with a custom compare function. I think you need to do some basic debugging here - output the contents of the array after it has been sorted (providing it is not too large), so you can eliminate that as being the problem. Then, in the CodeTitleComparer class, output the names of the two items being compared (and the result), so you can track the progress of the binary search function.

 

Good luck :cool:

Never trouble another for what you can do for yourself.
Posted

Right - I've sorted it!

 

After several days messing around with other problems I've come back to it (always a wise thing to do!) and noticed where I've gone wrong!

 

The answer is fairly straightforward, when you stand back and look. How does the container (or array, I suppose) know what it's sorting on? The answer is not the current class, but the object that is stored within the array. Because I am using nested classes I was referring directly to the comparers defined within my current class, whereas I should have been looking at the codes within the array. Simple, really, but when you're tying yourself up in knots with tree structures things can become a little bleary!

 

I'd like to thank you all for your direction and help.

 

 

Anyway, have a good weekend, plenty of beer, and (for those in the UK) enjoy the sun!

 

 

Paul. ;)

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...