0

I have a list containing data with string and number. I have to order it in ascending and descending order.

        id    data
    ------------------
        1     data1@%
        2     data10
        3     data
        4     @$data
        5     data2

I fetch the record and store it in list "List". Then I order it in ascending, but "data10" is coming in b/w "data1" and "data2". Below is my code

var o/p = List.OrderBy(x => x.data);

expected output - data1, data2 and data10
anand
  • 1,559
  • 5
  • 21
  • 45
  • order it by id instead – active92 Nov 11 '16 at 04:42
  • Yes, that's dictionary ordering. – Rahul Nov 11 '16 at 04:42
  • I assume your code does not actually include `var o/p = ...` – Abion47 Nov 11 '16 at 04:43
  • i have to take the data column only – anand Nov 11 '16 at 04:44
  • What result are you expecting? (the field is a `string` and is being ordered correctly) –  Nov 11 '16 at 04:44
  • @anand but the sequence you are getting will be data1, data10 and data2 if you order it by data. – active92 Nov 11 '16 at 04:48
  • create a new column by splitting the number from data and order by the new column you will get the desired result. – Sriram Nov 11 '16 at 04:52
  • check my (@Nayan Godhani) answer it's works your need –  Nov 11 '16 at 04:54
  • Only solution is to retrieve a number from string and sort collection by this number. Which answers below provides. So main question is **how to retrieve numbers from string**. For answering this question you need provide more information about `data` value, is "data" part constant or it change, if it change then how it change etc... Of cource if it constant then use first option in @Abion47 answer. – Fabio Nov 11 '16 at 07:12
  • @Fabio And if it's not constant, use the second option. – Abion47 Nov 11 '16 at 07:45

2 Answers2

2

You are currently sorting it based on the string values, which will sort it by dictionary value. In a dictionary, "10" will appear between "1" and "2" because that is alphabetical order - it does not recognize that it is sorting numbers.

True alphanumeric sorting can get pretty complex, but based on your data you might be able to simplify it. Assuming your string "data1", "data2", and "data10" is a consistent pattern, you can do something like this:

var op = List.OrderBy(x => int.Parse(x.data.substring(4)));

Alternatively, if the value before the number isn't a constant length, you can use Regex to pull the number value out:

var op = List.OrderBy(x => int.Parse(Regex.Match(x.data, "\\d+").Value));
Abion47
  • 22,211
  • 4
  • 65
  • 88
0

To get what you want, you need to pad the numeric portion in your order by clause, something like:

var o/p = List.OrderBy(x => PadNumbers(x.Data));

where PadNumbers could be defined as StackOverflow user Nathan has written here:

public static string PadNumbers(string input)
{
    return Regex.Replace(input, "[0-9]+", match => match.Value.PadLeft(10, '0'));
}

This pads zeros for any number (or numbers) that appear in the input string so that OrderBy sees:

data0000000001
data0000000010
data0000000002

The padding only happens on the key used for comparison. The original strings (without padding) are preserved in the result.

Note : This approach assumes a maximum number of digits for numbers in the input.

Community
  • 1
  • 1