Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LINQ query that combines grouping and sorting

I am relatively new to LINQ and currently working on a query that combines grouping and sorting. I am going to start with an example here. Basically I have an arbitrary sequence of numbers represented as strings:

List<string> sNumbers = new List<string> {"34521", "38450", "138477", "38451", "28384", "13841", "12345"}

I need to find all sNumbers in this list that contain a search pattern (say "384") then return the filtered sequence such that the sNumbers that start with the search pattern ("384") are sorted first followed by the remaining sNumbers that contain the search pattern somewhere. So it will be like this (please also notice the alphabetical sort with in the groups):

{"38450", "38451", "13841", "28384", "138477"}

Here is how I have started:

outputlist = (from n in sNumbers
                where n.Contains(searchPattern
                select n).ToList();

So now we have all number that contain the search pattern. And this is where I am stuck. I know that at this point I need to 'group' the results into two sequences. One that start with the search pattern and other that don't. Then apply a secondary sort in each group alphabetically. How do I write a query that combines all that?

like image 987
Fike Rehman Avatar asked Feb 12 '16 22:02

Fike Rehman


3 Answers

I think you don't need any grouping nor list splitting for getting your desired result, so instead of answer about combining and grouping I will post what I would do to get desired result:

sNumbers.Where(x=>x.Contains(pattern))
    .OrderByDescending(x => x.StartsWith(pattern)) // first criteria
    .ThenBy(x=>Convert.ToInt32(x)) //this do the trick instead of GroupBy
    .ToList();
like image 142
tede24 Avatar answered Oct 22 '22 23:10

tede24


This seems fairly straight forward, unless I've misunderstood something:

List<string> outputlist = 
    sNumbers
        .Where(n => n.Contains("384"))
        .OrderBy(n => int.Parse(n))
        .OrderByDescending(n => n.StartsWith("384"))
        .ToList();

I get this:

outputlist

like image 29
Enigmativity Avatar answered Oct 22 '22 22:10

Enigmativity


var result = sNumbers
                        .Where(e => e.StartsWith("384"))
                        .OrderBy(e => Int32.Parse(e))
                .Union(sNumbers
                        .Where(e => e.Contains("384"))
                        .OrderBy(e => Int32.Parse(e)));
like image 41
Alex S Avatar answered Oct 22 '22 22:10

Alex S