Click here to Skip to main content
15,896,154 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am writing a program that uses the haversine formula to determine the x nearest locations to a lat/lon. It takes a base lat and lon and compares it to the lat and lon of every location element in an xml file and then it adds it to a custom List(Result) containing the site lat, site lon and haversine result (which is a decimal type and containes the distance between the base and the xml entry). I have it all working fine with no errors but I thought that there were closer locations than some of the top 10 displayed after sorting in the console so I moved it to wpf and got it to plot the top 10 onto a map (the Bing Maps Control for WPF) and also looked at the xml file. I found quite a few locations that were much, much, much closer to the base than the top 10 were so I then got it to add each haversine result to a new List(string) and print a huge messagebox with 1 result on each line and I looked through and saw that they were sorted, but incorrectly:

It should be (this is a very simplified example, the real would be decimals like 109.84477432975):
10, 50, 100, 150, 200, 500
But instead it is:
10, 100, 150, 200, 50, 500

It sorts them into groups of first digits and then sorts those groups by value. I get this in file explorer when I have consecutively named files. They only sort in the correct order if I put a zero at the start of the ones with single digits. How can I stop this and make the DECIMALS order correctly? I cannot change the haversine results once they are calculated and I am sorting my custom type list:
C#
public class Result
{
     public string SiteID { get; set; }
     public string SiteName { get; set; }
     public decimal SiteLat { get; set; }
     public decimal SiteLon { get; set; }
     public string HavResult { get; set; }
}

...by using this:
C#
results.Sort(delegate(Result result1, Result result2) { return result1.HavResult.CompareTo(result2.HavResult); });

And I am sorting the list by only the HavResult part. How can it be sorted correctly, thank you.
Posted

Your problem is that you are sorting strings not numbers!
C#
public string HavResult { get; set; }

Try to convert it to decimal first:
C#
Convert.ToDecimal(result1.HavResult).CompareTo(Convert.ToDecimal(result2.HavResult));
 
Share this answer
 
Comments
Henry Hunt 1-Jan-14 9:45am    
Oh my god! I completely missed it ahaha. Thank you for that! It works perfectly now.
Kornfeld Eliyahu Peter 1-Jan-14 9:47am    
You welcome!
You order by HavResult, and that's a string, and because 50 actually comes after 200 in alphabetical order, 200 comes before 50. So, you need to change the type of HavResult into double or decimal. Don't know what to choose? Then have a look here[^]. After changing the type of HavResult, you don't need to update your sorting code because double and decimal also have a CompareTo method.
 
Share this answer
 
If you can structure your class so that the Haversine value is Type Decimal, then getting a list sorted in ascending order from a List of your Class is very easy using Linq:
C#
// in addition to whatever other 'using statements are required, these must be present
using System.Collections.Generic;
using System.Linq;

// sample class
public class locationData
{
    public double latitude;
    public double longitude;
    public decimal haversine;

    public locationData(double lat, double lon, decimal haversn)
    {
        latitude = lat;
        longitude = lon;
        haversine = haversn;
    }
}

// assume you created a bunch of instances
// of locationData in a List<locationdata>
// named 'locList

// sample code to create a sorted list of
// the haversine values in ascending order
List<decimal> dSortList = locList.Select(x => x.haversine).OrderBy(x => x).ToList();
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900