user9969
user9969

Reputation: 16040

Sorting a collection of numeric Strings

I need the ability to sort a collection of customers which contains a property of numeric string.

How Can I sort the below collection by code in numeric order. Again Code is a string.

           class Program
           {
              static void Main(string[] args)
              {
                 SortableObservableCollection<Customer> customerList = new SortableObservableCollection<Customer>();
                 customerList.Add(new Customer() {Name = "Jo", Code = "1"});
                 customerList.Add(new Customer() { Name = "Jo", Code = "10" });
                 customerList.Add(new Customer() { Name = "Jo", Code = "11" });
                 customerList.Add(new Customer() { Name = "Jo", Code = "9" });
                 customerList.Add(new Customer() { Name = "Jo", Code = "7" });
                 customerList.Add(new Customer() { Name = "Jo", Code = "12" });
                 customerList.Add(new Customer() { Name = "Jo", Code = "13" });
                 customerList.Add(new Customer() { Name = "Jo", Code = "2" });
                 customerList.Add(new Customer() { Name = "Jo", Code = "5" });
                 customerList.Add(new Customer() { Name = "Jo", Code = "7" });

                 //Order them by Code How
              }
           }

           public class Customer
           {
              public string Name { get; set; }
              public string Code { get; set; }
           }

Thanks for any suggestions

Upvotes: 7

Views: 19357

Answers (4)

Anthony Pegram
Anthony Pegram

Reputation: 126804

How confident are you that the Code is (a) numeric and (b) present?

var sortedList = customerList.OrderBy(c => int.Parse(c.Code));

If you have doubts, try another approach

Func<string, bool> isInteger = s => { int temp; return int.TryParse(s, out temp); };
var query = customerList.OrderBy(c => isInteger(c.Code) ? int.Parse(c.Code) : int.MaxValue);

Or to reduce the number of attemtps to parse the value and to keep the logic in one delegate:

Func<string, int> intParser = input =>
{
    int result;
    if (!int.TryParse(input, out result))
        return int.MaxValue; 

    return result;
};

var query = customerList.OrderBy(c => intParser(c.Code)); // .ToList() if you wish

Note: I'm using int.MaxValue to move non-integer inputs to the back of the line. You can choose another value depending upon where you might want those objects.

Upvotes: 7

Jon Skeet
Jon Skeet

Reputation: 1500035

Option 1: implement IComparer<Customer> and parse the Code within that

Option 2: use LINQ to do the same thing:

customerList = customerList.OrderBy(c => int.Parse(c.Code)).ToList();

Option 3: change the Customer class so that a numeric value is stored as a numeric type :)

EDIT: As noted, this will throw an exception if you give it a customer with a non-numeric code.

Also, I'm calling ToList() because I assumed you still needed it to be a list. If you just need to iterate over the results in order, then use:

IEnumerable<Customer> ordered = customerList.OrderBy(c => int.Parse(c.Code));

Note that if you iterate over that twice, however, it will perform all the parsing and sorting twice too.

Upvotes: 20

Eric Lippert
Eric Lippert

Reputation: 659994

If the keys are always just numbers and those numbers are always convertible to ints then it is pretty straightforward. Just convert them to ints.

var sorted = from customer in customerList orderby Int32.ParseInt(customer.Code) select customer;

If any of them are not ints then this will crash.

Another way to do it is to pad the string out with leading zeros:

var sorted = from customer in customerList orderby PadToTenDigits(customer.Code) select customer;

where PadToTenDigits is a method left as an exercise, that turns "1" into "0000000001" and "1000" into "0000001000", and so on.

If you have to do true "numeric" sorting on complex codes, where, say, code "A300-B" sorts before "A1000-XYZ", then you have a harder problem on your hands. The trick there is to break up the code into "parts" and do a stable sort on each part. Basically, a radix sort.

Upvotes: 7

rkellerm
rkellerm

Reputation: 5512

Try LINQ to Objects:

var result = from c in customerList
             orderby Int.Parse(c.Code)
             select c;

Upvotes: -2

Related Questions