Home > other >  Sorting a formatted LINQ query
Sorting a formatted LINQ query

Time:12-01

A sequence of non-empty strings stringList is given, containing only uppercase letters of the Latin alphabet. For all strings starting with the same letter, determine their total length and obtain a sequence of strings of the form "S-C", where S is the total length of all strings from stringList that begin with the character C. Order the resulting sequence in descending order of the numerical values of the sums, and for equal values of the sums, in ascending order of the C character codes.

This question is related to one of my previous questions.

One solution that works is this one:

stringList.GroupBy(x => x[0]).Select(g => $"{g.Sum(x => x.Length)}-{g.Key}");

The problem is that with this given example I don't know where to add the OrderByDescending()/ThenBy() clauses in order to get the correctly sorted list.

CodePudding user response:

Create an intermediate data structure to store needed info and use it for sorting and then building the output:

stringList
    .GroupBy(x => x[0])
    .Select(g => (Length: g.Sum(x => x.Length), Char: g.Key))
    .OrderByDescending(t => t.Length)
    .ThenBy(t => t.Char)
    .Select(t => $"{t.Length}-{t.Char}");

CodePudding user response:

You're almost there. The cleanest way of doing it would be to make a more complex object with the properties you care about, use those to sort, then keep only what you want in the output. Like:

stringList
    .GroupBy(x => x[0])
    .Select(g => new {
        Len = g.Sum(x => x.Length),
        Char = g.Key,
        Val = $"{g.Sum(x => x.Length)}-{g.Key}"
    })
    .OrderByDescending(x => Len)
    .ThenBy(x => x.Char)
    .Select(x => x.Val);

CodePudding user response:

You can add a Select after the GroupBy to transform the groups into an anonymous object containing the things you want to sort by. Then you can use OrderByDescending and ThenBy to sort. After that, Select the formatted string you want:

stringList.GroupBy(x => x[0]) // assuming all strings are non-empty
    .Select(g => new {
        LengthSum = g.Sum(x => x.Length),
        FirstChar = g.Key
    })
    .OrderByDescending(x => x.LengthSum)
    .ThenBy(x => x.FirstChar)
    .Select(x => $"{x.LengthSum}-{x.FirstChar}");

Alternatively, do it in the query syntax with let clauses, which I find more readable:

var query = from str in stringList
    group str by str[0] into g
    let lengthSum = g.Sum(x => x.Length)
    let firstChar = g.Key
    orderby lengthSum descending, firstChar
    select $"{lengthSum}-{firstChar}";
  • Related