Sorting Arrays

Element6

Well-known member
Joined
Feb 16, 2010
Messages
85
Programming Experience
5-10
Ok well .NET definately makes sorting Arrays easy. I have a quick question though if anyone knows.

I am using the Array type .Sort function to sort my array.

By default it places the result Array into Ascending order Least to Greatest

How do I change that to Descending order Greatest to Least?
and
How do I change it to Closest to logic? or does that not exist?

Assume there is an Array of Numbers 0,13,21,-2,4,5,1.34 and I want them to sort closest to 0 or some other arbitray value; the Output should look similar to:

0,1.34,-2,4,5,13,21

Is there anyway of doing this? or do I have to write the routine?
 
Unfortunately the sort method is terrible with numbers. It will list them like 1,11,2,21,3 which makes no sense to me. I just think it was just laziness.
 
Well there is a trick with numbers and sorting them; an old lazy developers trick us out-of-date developers do.

Convert your numbers in segments of 2 digits at a time to a character and store them as characters, with an indicator to reconvert to numbers. So when you pass them through sort algorithms you get the same result as if they were literal.

Be sure to start your map at 33-132 so that you map 0-99 to 33-132 using a 33 offset. That way you get usable characters.

Then just concat the characters and you get a nice string expression that is encoded numerical data. Do a quick sort. La Poof! Wala, sorted numbers.

I'm lazy, I hate programming too much if I can help it so I do stupid stuff like that so I don't have to.


Ok, well I had to write a Closest to Zero Sort alogrithm, *sigh* I always do stuff noone else develops; *starting to wonder if I my logic is skewed or everyone elses is.*
 
Numbers are sorted perfectly!

VB.NET:
Dim a() As Integer = {1, 11, 2, 22, 5}
        Array.Sort(a)
        For Each i As Integer In a
            Debug.Print(i)
        Next

Unfortunately ... many people think that "11" is number. It's not. It's a ... string! Also some ppl think that "dim a as string = 5" makes "a" a "number". No. "a" is still a string.

Do yourself a favor and use "Option Strict ON" ...
 
VB.NET:
Dim num() As Single = {0, 13, 21, -2, 4, 5, 1.34}
Array.Sort(num, Function(x As Single, y As Single) Math.Abs(x).CompareTo(Math.Abs(y)))
If you don't support Lambda expressions you have to make that a real Function and use AddressOf operator in Sort call.
 
Your right, it has been a while since I played with that. It is a listbox that does not sort numbers correctly.
 
Thanks for the listbox hint; but I'm trying to keep my code small not trying to include things I don't need and grow a normally 1mb .exe into 200mb file which WILL occur if I had all those gadgets.

The sort function needs to be written I think end of story. This is a console application and is intended to migrate to a service not an application front-end.

Microsoft does a great job on useful other stuff like the listbox, but... They forget people do have other constraints. Such as "Security", and Memory and disk management.

Sometimes the best solution; is just write the code.

And for those that are getting to know me, I AM very nit picky about security and code optimization. Things that are one time fly-bys; dont get controls they get written; others that are intensive I inculde.
 
In order to reverse the sort from ascending to descending, first do a regular sort, and then do

Array.Reverse(arrayname)


Make sure you sort it first. The Array.Reverse() method will simply rearrange the values from top to bottom without sorting them.
 
Element6 said:
The sort function needs to be written I think end of story.
Since you didn't understand I will post the non-lambda function spelled out for you also:
VB.NET:
Function AbsSort(x As Single, y As Single) As Integer
    Return Math.Abs(x).CompareTo(Math.Abs(y))
End Function
VB.NET:
Array.Sort(num, AddressOf AbsSort)
Application type is not relevant here. I do recommend you start out with VB 2008 though, even VB 2010 is right around the corner now (RC). VB 2005 you say you are using is out-dated now.
Solitaire said:
In order to reverse the sort from ascending to descending, first do a regular sort, and then do
It would be better to just swap the operands in the CompareTo expression, that is, if a "reverse" sort was needed, which it is not here.
 
Ok. I understand the code.

Except I need to expand on the code you provided.

My origional problem was Closest to 0; I later clarified Closest to N. Ideally, I want to send the offset as N how would I pass the parameter of N in this case?

VB.NET:
num() = {3, 12, -.123, 5.1, 1002, 23}

Function AbsSort(x As Single, y As Single) As Integer
    Return Math.Abs(x).CompareTo(Math.Abs(y))
End Function

Array.Sort(num, AddressOf AbsSort)

Pseduo Code of :
VB.NET:
num() = {3, 12, -.123, 5.1, 1002, 23}

Function AbsSort([B][I]n as decimal[/I][/B], x As Single, y As Single) As Integer
    Return Math.Abs(x[B][I]-n[/I][/B]).CompareTo(Math.Abs(y)[B][I]+n[/I][/B])
End Function

Array.Sort(num, AddressOf AbsSort)

How do I determine my signs?

The only solution I know works (doesn't mean it's the only one available), I much rather do it the way you have expressed it can be done, is...

Take the array (num)
Create 2 temporary Arrays (NumLower, NumUpper)
Move everything that is lower then N into NumLower
Move everything that is Higher or equal to N into NumUpper
Sort NumLower and NumUpper

Recombine according to Values differences.

Are you suggesting something like
VB.NET:
num() = {3, 12, -.123, 5.1, 1002, 23}

Function AbsSort([B][I]n as decimal[/I][/B], x As Single, y As Single) As Integer
    Dim x1 as single = x
    Dim y1 as single = y
    If (x>n) then 
        x1 = x-n
        y1 = y+n
    Else
        x1 = x+n
        y1 = y-n
    End If
    Return Math.Abs([B][I]x1[/I][/B]).CompareTo(Math.Abs([B][I]y1[/I][/B]))
End Function

Array.Sort(num, AddressOf AbsSort)

I would rather sort using the above method; if you can suggest away of passing N that I am totally overlooking.
 
Last edited:
JohnH is quite correct of course, but for more information on sorting arrays and collections, you might like to follow the Blog link in my signature and check out my three part post on the subject.
 
Error; I'm sorry sometimes I can ask stupid questions without looking at the problem.

Wil this work? Haven't tried it yet.
VB.NET:
    Public Function AbsSort(ByVal x As Decimal, ByVal y As Decimal) As Integer
        Return Math.Abs(x).CompareTo(Math.Abs(y))
    End Function

    Public Function SortClosestToN(ByVal AnArrayOfNumbers As Decimal(), ByVal ValueOfN As Decimal) As Decimal()
        Dim x As Long

        For x = 0 To AnArrayOfNumbers.Length - 1
            AnArrayOfNumbers(x) = AnArrayOfNumbers(x) - ValueOfN
        Next

        Array.Sort(AnArrayOfNumbers, AddressOf AbsSort)

        For x = 0 To AnArrayOfNumbers.Length - 1
            AnArrayOfNumbers(x) = AnArrayOfNumbers(x) + ValueOfN
        Next

        Return AnArrayOfNumbers
    End Function

    Sub Main()
        Dim num() As Decimal = {3, 12, -0.123, 5.1, 1002, 23}

        num = SortClosestToN(num, 33)
    End Sub

My logic was way out wack and I was looking at the problem from a process level not a mathematics one.
 
Last edited:
VB.NET:
Math.Abs(x - n).CompareTo(Math.Abs(y - n)
With same data array the result where n=4 is:
4, 5, 1.34, 0, -2, 13, 21
If you have to use the explicit function you have to declare 'n' as a private field so that the function can access it (inline any local variable will do). The Comparison(Of T) delegate signature can't be changed.
 
Back
Top