Como obter o primeiro registro em cada grupo usando o Linq

133

Considerando os seguintes registros:

   Id          F1            F2             F3 
 -------------------------------------------------
   1           Nima          1990           10
   2           Nima          1990           11
   3           Nima          2000           12
   4           John          2001           1
   5           John          2002           2 
   6           Sara          2010           4

Desejo agrupar com base no F1campo, classificar Ide obter todos os campos do primeiro registro do grupo semelhante a esses registros:

   Id          F1            F2             F3 
 -------------------------------------------------
   1           Nima          1990           10
   4           John          2001           1
   6           Sara          2010           4

Como posso fazer isso usando o linq?

Arian
fonte

Respostas:

127
    var res = from element in list
              group element by element.F1
                  into groups
                  select groups.OrderBy(p => p.F2).First();
Alireza
fonte
4
Tão feliz que eu encontrei isso. Recebi a mensagem de erro "O método 'First' pode ser usado apenas como uma operação de consulta final. Considere usar o método 'FirstOrDefault' nesta instância." do seu exemplo. Somente operação na lista que fiz depois que a consulta estava passando myResult.ToList () para um método. Usando FirstOrDefault resolvido embora
aghost
Seriam OrderBy(p => p.Id), eles queriam que ele fosse ordenado por ID e não pela coluna do ano.
Mike Flynn
Você pode, por favor
fornecer
E se quiser recuperar o primeiro e o último item do grupo?
Sandeep Pandey
176
var result = input.GroupBy(x=>x.F1,(key,g)=>g.OrderBy(e=>e.F2).First());
King King
fonte
2
Isso me mostrou o caminho usando a sintaxe fluente. As sobrecargas do GroupBy parecem oferecer muito poder - uma a ser adicionada à longa lista de aprendizado!
Rogersillito
1
@rogersillito é por isso que é chamada de consulta (Language Integrated Query - LINQ), também o GroupBy tem muitas sobrecargas, mas há apenas alguns sendo comumente usados, também depende da preferência pessoal, como alguns preferem escrevê-la como .GroupBy(x=>x.F1).Select(g=>...), pode parecer mais fácil de entender.
King King
11
Você deve substituir .First()com .FirstOrDefault()ou você receberá a exceção:The method 'First' can only be used as a final query operation. Consider using the method 'FirstOrDefault' in this instance instead.
Nikolay Kostov
5
@NikolayKostov Eu sei disso, mas assumi que o LINQ aqui é usado como LINQ para objeto, não LINQ para entidades, para que possamos usá-lo com segurança .First(). A pergunta do OP parece realmente se importar apenas com o linq para o objeto, embora ele também tenha marcado a pergunta linq-to-entities(não tenho certeza se ele entendeu o que é isso).
King King
1
Gostei desta resposta, Nice.
AJAS Aju
8

O awnser de @Alireza está totalmente correto, mas você deve observar que ao usar este código

var res = from element in list
          group element by element.F1
              into groups
              select groups.OrderBy(p => p.F2).First();

que é semelhante a esse código porque você solicitou a lista e, em seguida, agrupa para obter a primeira linha de grupos

var res = (from element in list)
          .OrderBy(x => x.F2)
          .GroupBy(x => x.F1)
          .Select()

Agora, se você quiser fazer algo mais complexo, como obter o mesmo resultado de agrupamento, mas pegar o primeiro elemento de F2 e o último elemento de F3 ou algo mais personalizado, poderá fazê-lo estudando o código abaixo

 var res = (from element in list)
          .GroupBy(x => x.F1)
          .Select(y => new
           {
             F1 = y.FirstOrDefault().F1;
             F2 = y.First().F2;
             F3 = y.Last().F3;
           });

Então você terá algo como

   F1            F2             F3 
 -----------------------------------
   Nima          1990           12
   John          2001           2
   Sara          2010           4
Stavros Koureas
fonte
1
O delimitador ou separador do novo objeto deve ser vírgula e não-vírgula. Verifique.
Naredla Nithesh Reddy
3

Use-o para conseguir o que deseja. Em seguida, decida quais propriedades você deseja retornar.

yourList.OrderBy(l => l.Id).GroupBy(l => new { GroupName = l.F1}).Select(r => r.Key.GroupName)
Rubens Mussi Cury
fonte