Home > database >  c# groupby orderby thenby Try specifying the type arguments explicitly
c# groupby orderby thenby Try specifying the type arguments explicitly

Time:03-04

I want to group using Grade and sort in descending order based on the number of elements in each group, then use the Number property to sort each group element in ascending order. I tried but it doesn't work. Can you help me on what I'm doing wrong?

Here is the error content:
The type arguments for method 'System.Linq.Enumerable.OrderBy<TSource,TKey>(System.Collections.Generic.IEnumerable, System.Func<TSource,TKey>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp6
{
    internal class Program
    {
        static void Main(string[] args)
        {
            List<Test> list = new List<Test>
            {
                new Test { Grade = "C", Name = "apple1", Number = 10 },
                new Test { Grade = "C", Name = "apple2", Number = 90 },
                new Test { Grade = "C", Name = "apple3", Number = 30 },
                new Test { Grade = "B", Name = "orange1", Number = 12 },
                new Test { Grade = "B", Name = "orange2", Number = 31 },
                new Test { Grade = "A", Name = "pineapple1", Number = 63 },
                new Test { Grade = "A", Name = "pineapple2", Number = 13 },
                new Test { Grade = "A", Name = "pineapple3", Number = 23 },
                new Test { Grade = "A", Name = "pineapple4", Number = 93 },
                new Test { Grade = "A", Name = "pineapple5", Number = 463 },
                new Test { Grade = "A", Name = "pineapple6", Number = 14 },
                new Test { Grade = "D", Name = "watermelon", Number = 74 }
            };

            //

            //CS0411
            //The type arguments for method cannot be inferred from the usage.
            //Try specifying the type arguments explicitly.
            var aaa = list.GroupBy(x => x.Grade, x => (x.Name, x.Number))
                .Where(g => g.Count() >= 1)
                .OrderByDescending(g => g.Count())
                .ThenBy(g => g.Select(a => a.Number).ToList().Sort((x, y) => x.CompareTo(y)))
                .ToList();

            //expected answers
            //{ Grade = "A", Name = "pineapple2", Number = 13 }
            //{ Grade = "A", Name = "pineapple6", Number = 14 }
            //{ Grade = "A", Name = "pineapple3", Number = 23 }
            //{ Grade = "A", Name = "pineapple1", Number = 63 }
            //{ Grade = "A", Name = "pineapple4", Number = 93 }
            //{ Grade = "A", Name = "pineapple5", Number = 463 }
            //{ Grade = "C", Name = "apple1", Number = 10 }
            //{ Grade = "C", Name = "apple3", Number = 30 }
            //{ Grade = "C", Name = "apple2", Number = 90 }
            //{ Grade = "B", Name = "orange1", Number = 12 }
            //{ Grade = "B", Name = "orange2", Number = 31 }
            //{ Grade = "D", Name = "watermelon", Number = 74 }
        }
    }
    class Test
    {
        public string Grade { get; set; }
        public string Name { get; set; }
        public int Number { get; set; }
    }
}

CodePudding user response:

I want to group using Grade and sort in descending order based on the number of elements in each group, then use the Number property to sort each group element in ascending order.

That's not what ThenBy is for. ThenBy provides a secondary ordering for the same sequence. It's not meant to perform a sort within items in the sequence. (Additionally, the last part of your lambda expression in ThenBy is List<T>.Sort, which returns void... whereas the compiler expects a delegate that returns "the thing you want to perform secondary ordering by".)

The "outer sequence" ends up being a sequence of groups. If you want to transform each of those groups, you need to use Select. So I suspect you want:

var aaa = list.GroupBy(x => x.Grade, x => (x.Name, x.Number))
    // Order the groups by descending size of group
    .OrderByDescending(g => g.Count())
    // Order the elements of each individual group by number
    .Select(group => group.OrderBy(a => a.Number).ToList())
    .ToList();

Note: I removed the Where clause as GroupBy never yields any empty groups.

Alternatively, given that the elements of a group returned by GroupBy are the same as in the original sequence, you could order the original sequence by number first:

var aaa = list
    .OrderBy(x => x.Number)
    .GroupBy(x => x.Grade, x => (x.Name, x.Number))
    .OrderByDescending(g => g.Count())
    .ToList();

That way you still end up with a sequence of IGrouping elements, instead of just a sequence of lists... which means you can still access the key for each group.

  • Related