Feature request for a new sort method

@Ian_Kennedy
i not want speak agains a feature request.

for my understanding a sort method return -1,0,1
so if you input two objects it can compare each other.
if you need externel sort information you can store it at the objects or a object method request it.
if your object return a number or string both can be compared with <=>

@MarkusR That is the case for the version that takes a method, however SortWith isn’t available with a method parameter. Which is what my request is asking for.

@Eric_Williams That is pretty much what I am doing. Except that I have support built in for 2 sorting columns and both ascending and descending sort on each.

How do you differentiate between signed and unsigned integer array types?

-Karen

There isn’t a way to do this in Xojo as far as I can tell. Because the code has to be able to accept arrays of any type, the parameter type is Variant and it has to use Variant’s ArrayElementType function to determine the type of the array. That function makes no differentiation between the various Integer subtypes.

It’s really quite limiting. Ideally, one could handle arrays in a generic fashion but the existing design doesn’t permit this. So my code has to do the best it can by having handlers for every possible type it can anticipate.

I think that all this mess of doubts, not even proving what would be the best way to solve an imaginary problem, makes sense of having just basic building blocks letting the users to create their specific solution to handle their specific problems. A generic one would take “Generics” and Xojo can’t handle Generics yet.

For instance, those are the methods we find in another framework that handles generics:

Sort(Array, Array, Int32, Int32, IComparer) Sorts a range of elements in a pair of one-dimensional Array objects (one contains the keys and the other contains the corresponding items) based on the keys in the first Array using the specified IComparer.
Sort(Array, Int32, Int32, IComparer) Sorts the elements in a range of elements in a one-dimensional Array using the specified IComparer.
Sort(Array, Array, Int32, Int32) Sorts a range of elements in a pair of one-dimensional Array objects (one contains the keys and the other contains the corresponding items) based on the keys in the first Array using the IComparable implementation of each key.
Sort(Array, Int32, Int32) Sorts the elements in a range of elements in a one-dimensional Array using the IComparable implementation of each element of the Array.
Sort(Array, IComparer) Sorts the elements in a one-dimensional Array using the specified IComparer.
Sort(Array, Array) Sorts a pair of one-dimensional Array objects (one contains the keys and the other contains the corresponding items) based on the keys in the first Array using the IComparable implementation of each key.
Sort(Array) Sorts the elements in an entire one-dimensional Array using the IComparable implementation of each element of the Array.
Sort(Array, Array, IComparer) Sorts a pair of one-dimensional Array objects (one contains the keys and the other contains the corresponding items) based on the keys in the first Array using the specified IComparer.
Sort(T[]) Sorts the elements in an entire Array using the IComparable generic interface implementation of each element of the Array.
Sort(T[], IComparer) Sorts the elements in an Array using the specified IComparer generic interface.
Sort(T[], Comparison) Sorts the elements in an Array using the specified Comparison.
Sort(T[], Int32, Int32) Sorts the elements in a range of elements in an Array using the IComparable generic interface implementation of each element of the Array.
Sort(T[], Int32, Int32, IComparer) Sorts the elements in a range of elements in an Array using the specified IComparer generic interface.
Sort<TKey,TValue>(TKey[], TValue[]) Sorts a pair of Array objects (one contains the keys and the other contains the corresponding items) based on the keys in the first Array using the IComparable generic interface implementation of each key.
Sort<TKey,TValue>(TKey[], TValue[], IComparer) Sorts a pair of Array objects (one contains the keys and the other contains the corresponding items) based on the keys in the first Array using the specified IComparer generic interface.
Sort<TKey,TValue>(TKey[], TValue[], Int32, Int32) Sorts a range of elements in a pair of Array objects (one contains the keys and the other contains the corresponding items) based on the keys in the first Array using the IComparable generic interface implementation of each key.
Sort<TKey,TValue>(TKey[], TValue[], Int32, Int32, IComparer) Sorts a range of elements in a pair of Array objects (one contains the keys and the other contains the corresponding items) based on the keys in the first Array using the specified IComparer generic interface.

I was going to pretty much do the same thing you did, but when I realized I could not handle the unsigned integer types I decides it was not worth the hassle of creating all the methods.

-Karen

I’m not clear on why you need to make that differentiation. Can you clarify?

Umm not an imaginary problem… I ran into the need a few weeks ago. Had to redesign my code to avoid having to do that.

-Karen

Equally, wanting to use the delegate sort method at the same time as SortWith is hardly an imaginary problem.

For now you can design your solution for your specific problem, when Xojo to introduce Generics, I bet they will expand the sort capabilities to cover generic cases able to avoid problems related to things like ints vs uints vs objects vs etc.

my thought is to use
aSortData.HowToSort=Array(aCol1, aCol2, aCol3)
only works with a class object
aSortData.Sort(CompareMethod)

this sortwith example are confusing for me

Var names() As String = Array("Mozart", "Bing", "Jackson", "Flintstone")
Var zips() As String = Array("04101", "04240", "04123", "04092")
names.SortWith(zips)

usually u have a object/struct with the name and zip propertie.
not split into 2 string arrays.

Because You need to create new arrays of the same data type…

But thinking about it more, I suppose one could use CType to both do assignments to a new array and to assign the elements back to the original array.

-karen

Check out my code. Xojo treats Integer and Integer subtypes as all the same type of object as far as I can tell. My technique also doesn’t require creating a new array as you are suggesting.

Well it certainly matters for sorting how the bits are interpreted
Dim i32 as int32 = &hFFFFFFFF

Dim ui32 As UInt32 = i32
If i32 = ui32 then
  MsgBox "Equal"
ElseIf i32 > ui32 then
  MsgBox "Larger"
Else
  MsgBox "Smaller"
End if

In my example I have a number of columns in a spreadsheet style arrangement. Each column is a separate class with a Data() array for the rows. The data in my columns is up to the user of the application. It is not a purpose built application for a given task.

Even with the example provided if you want to perform a reverse sort you want to be able to

Var names() As String = Array("Mozart", "Bing", "Jackson", "Flintstone")
Var zips() As String = Array("04101", "04240", "04123", "04092")
names.SortWith( AddressOf SortBackwards, zips)

Function SortBackwards( Element1 as String, Element2 as String )
    return Element1.Compare(Element2) * -1
End Function

Would do the job, if it were possible to call SortWith with a sort method.

Your example is pretty edge case and doesn’t really demonstrate anything other than Xojo’s lack of exception throwing during invalid assignments. First, you’re assigning an overflow value to the Int32 (&hFFFFFFFF is a 64-bit value) which gets interpreted as -1. Then, you’re assigning that negative value to an unsigned integer.

The comparison is working correctly: -1 will always be smaller than any unsigned integer.

so your workaround with help of Extends would be

names.SortWith(zips.Backwards())

a copy of data in reverse order.

(its early in the morning, just by intuition)

My final solution was similar but more general:

CopyDataToUndo ' (which I was doing anyway)
PopulateSortAndIndex aKey, aOrdinal ' Create a sort key and array of row indexes.

aKey.SortWith( aOrdinal )

for nRow = 0 to aKey.LastIndex
   Data( nRow ) = UndoData( aOrdinal( nRow ) ) ' You can adjust this to reverse sort
next

You can either reverse copy in the final loop or generate a key that is inverted and will sort backwards.

1 Like