1

I have a list, each element in the list is a string that contains date and integer in specific format: yyyyMMdd_number.

List<string> listStr = new List<string> { "20170822_10", "20170821_1", "20170823_4", "20170821_10", "20170822_11", "20170822_5",
                                          "20170822_2", "20170821_3", "20170823_6", "20170823_21", "20170823_20", "20170823_2"};

When use method listStr.Sort();

Result as below:

20170821_1
20170821_10
20170821_3
20170822_10
20170822_11
20170822_2
20170822_5
20170823_2
20170823_20
20170823_21
20170823_4
20170823_6

Expected Output:

20170821_1
20170821_3
20170821_10
20170822_2
20170822_5
20170822_10
20170822_11
20170823_2
20170823_4
20170823_6
20170823_20
20170823_21

The way: i think every string(day_number) will split with an underline, then compare and sort by number. But please suggest me LINQ solution or better way to sort in this case.

0

3 Answers 3

10

Since the dates are in the format that can be ordered lexicographically, you could sort by the date prefix using string ordering, and resolve ties by parsing the integer:

var sorted = listStr
    .OrderBy(s => s.Split('_')[0])
    .ThenBy(s => int.Parse(s.Split('_')[1]));

Demo.

Sign up to request clarification or add additional context in comments.

1 Comment

Exactly! Thank you for your effort! +1
2

I imagine any numeric ordering would first require converting the value to a numeric type. So you could split on the underscore, sort by the first value, then by the second value. Something like this:

list.OrderBy(x => x.Split('_')[0]).ThenBy(x => int.Parse(x.Split('_')[1]))

You could improve this, if necessary, by creating a class which takes the string representation on its constructor and provides the numeric representations (and the original string representation) as properties. Then .Select() into a list of that class and sort. That class could internally do type checking, range checking, etc.

1 Comment

I understand. Thank you for your effort! +1
1

The answers above are much easier to follow / understand, but purely as an alternative for academic interest, you could do the following:

var sorted = listStr.OrderBy(x => Convert.ToInt32(x.Split('_')[0])*100 + Convert.ToInt32(x.Split('_')[1]));

It works on the premise that the suffix part after the underscore is going to be less than 100, and turns the two elements of the string into an integer with the relative 'magnitude' preserved, that can then be sorted.

The other two methods are much, much easier to follow, but one thing going for my alternative is that it only needs to sort once, so would be a bit faster (although I doubt it is going to matter for any real-world scenario).

1 Comment

Thank you for clear explanation! I have learned one more method. +1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.