Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I sort a string of text followed by a number using LINQ

Tags:

c#

linq

I have been using the following sort:

var query = _cityRepository.GetAll(
               .OrderBy(item => item.RowKey.Substring(0, 4))
               .ThenBy(item => item.ShortTitle)

However I am having a problem because my ShortTitle looks like this:

Liverpool - 1
Liverpool - 2
...
Liverpool - 9
Liverpool - 10
Liverpool - 11
West Kirby - 1
West Kirby - 8
West Kirby - 12

When I sort this using LINQ it comes in the order

Liverpool - 1
Liverpool - 11
Liverpool - 12
Liverpool - 2
West Kirby - 1
West Kirby - 12
West Kirby - 8

The ShortTitle is always a string of words followed by a single hyphen and then a number.

Is there a way I can get this to sort correctly?

like image 889
Alan2 Avatar asked Jun 15 '12 13:06

Alan2


People also ask

Can you use LINQ on a string?

LINQ can be used to query and transform strings and collections of strings. It can be especially useful with semi-structured data in text files. LINQ queries can be combined with traditional string functions and regular expressions. For example, you can use the String.

How do I use ascending order in LINQ?

In LINQ, the OrderBy operator is used to sort the list/ collection values in ascending order. In LINQ, if we use order by the operator by default, it will sort the list of values in ascending order. We don't need to add any ascending condition in the query statement.

How do you order alphabetically in LINQ?

SelectedValue) . OrderBy(s=> s.Name). ToList(); The order by does nothing, just executes the query, the ToList will do the sort for the original query.

How do I sort in LINQ descending order?

If you want to rearrange or sort the elements of the given sequence or collection in descending order in query syntax, then use descending keyword as shown in below example. And in method syntax, use OrderByDescending () method to sort the elements of the given sequence or collection.


2 Answers

It's because you are sorting them as strings, and for strings 11 comes before 2. You'll need to parse the ShortTitle to give you the (I'm assuming) int value at the end, and sort by that.

Your LINQ query can be changed to this for it to work:

var query = _cityRepository.GetAll(
           .OrderBy(item => item.RowKey.Substring(0, 4))
           .ThenBy(item => item.ShortTitle.Split('-').First())
           .ThenBy(item => Convert.ToInt16(item.ShortTitle.Split().Last()));
like image 109
NominSim Avatar answered Oct 20 '22 12:10

NominSim


Try this

List<string> list = new List<string>() { 
    "Liverpool - 1",
    "Liverpool - 11",
    "Liverpool - 12",
    "Liverpool - 2",
    "West Kirby - 1",
    "West Kirby - 12",
    "West Kirby - 8" };
var sortedList = list.CustomSort().ToArray();    


public static class MyExtensions
{
    public static IEnumerable<string> CustomSort(this IEnumerable<string> list)
    {
        int maxLen = list.Select(s => s.Length).Max();

        return list.Select(s => new
        {
            OrgStr = s,
            SortStr = Regex.Replace(s, @"(\d+)|(\D+)", m => m.Value.PadLeft(maxLen, char.IsDigit(m.Value[0]) ? ' ' : '\xffff'))
        })
        .OrderBy(x => x.SortStr)
        .Select(x => x.OrgStr);
    }

}
like image 42
L.B Avatar answered Oct 20 '22 12:10

L.B