0

How to sort a List which holds values as mentioned below

67.232,S
98.122,F
12.211,H

and so ..

Now I need to sort the above List value like

12.211,H
67.232,S
98.122,F

Initially I tried with below piece of code (which I got from Sorting a List of Strings numerically (1,2,...,9,10 instead of 1,10,2))

 Position.Add(25.251,A);
 Position.Sort((x, y) => ExtractNumber(x).CompareTo(ExtractNumber(y)));
       static int ExtractNumber(string text)
        {
            Match match = Regex.Match(text, @"^[^,]*");
            if (match == null)
            {
                return 0;
            }

            int value;
            if (!int.TryParse(match.Value, out value))
            {
                return 0;
            }

            return value;
        }

but its not working out for me Can anyone help me out please

Thanks

Community
  • 1
  • 1
Ganeshja
  • 2,675
  • 12
  • 36
  • 57

3 Answers3

2

You could parse the part that is numeric and use Enumerable.OrderBy:

list = list
    .Select(s => new { NumPart = s.Substring(0, s.LastIndexOf(',')), Item = s })
    .OrderBy(x => double.Parse(x.NumPart, CultureInfo.InvariantCulture))
    .Select(x => x.Item)
    .ToList();

Note that i've used CultureInfo.InvariantCulture because many cultures use comma as decimal separator.

DEMO

Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
1

I'd recommend using LINQ's OrderBy, which let's you specify a selector:

var myList = new List<string> { "12.211,H", ... };
var orderedList = myList
    // sort by the number column by splitting each record by comma and parsing the first field as a double
    .OrderBy(s => double.Parse(s.Split(',')[0]))
    .ToList();

This is slightly different than List.Sort() as it creates a sorted copy of the list rather than mutating the existing collection.

To do this via your original approach:

myList.Sort((x, y) => ExtractNumber(x).CompareTo(ExtractNumber(y)));

// note I've changed the use of int's to doubles since you seem to be working with fractions
static double ExtractNumber(string text)
        {
            var fields = text.Split(',');
            double value;
            if (fields.Length == 0
                || !double.TryParse(fields[0], out value))
            {
                return 0; // as in your original code, missing/unparseable values get treated as 0
            }            

            return value;
        }
ChaseMedallion
  • 20,860
  • 17
  • 88
  • 152
1

Your approach does not work because your numbers are not ints! If you are dealing with currencies use decimal. For technical and scientific oriented calculations use double.

static decimal ExtractNumber(string text)
{
    string[] parts = text.Split(',');
    decimal value;
    if (parts.Length > 0 &&
        Decimal.TryParse(parts[0], NumberStyles.Any,
                         CultureInfo.InvariantCulture, out value)) {
        return value;
    }
    return 0;
}

Also choose the invariant culture explicitly if your numbers always have a point as decimal separator. The German culture, for instance, uses a comma.

Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188