Comment obtenir le premier enregistrement de chaque groupe en utilisant Linq

133

Compte tenu des enregistrements suivants:

   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

Je souhaite regrouper en fonction du F1champ et trier Idet obtenir tous les champs du premier enregistrement du groupe similaire à ces enregistrements:

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

Comment puis-je faire cela en utilisant linq?

Ariane
la source

Réponses:

127
    var res = from element in list
              group element by element.F1
                  into groups
                  select groups.OrderBy(p => p.F2).First();
Alireza
la source
4
Je suis tellement content d'avoir trouvé ça. J'ai reçu le message d'erreur "La méthode 'First' ne peut être utilisée que comme opération de requête finale. Pensez à utiliser la méthode 'FirstOrDefault' dans ce cas à la place." de votre exemple. Seule l'opération sur la liste que j'ai effectuée après que la requête a passé myResult.ToList () à une méthode. L'utilisation de FirstOrDefault a résolu le problème
hôte du
Serait-ce le cas OrderBy(p => p.Id), ils voulaient qu'il soit trié par ID et non par colonne d'année.
Mike Flynn
Pouvez-vous s'il vous plaît
fournir de l'
Que faire si vous souhaitez récupérer le premier et le dernier élément du groupe?
Sandeep Pandey le
176
var result = input.GroupBy(x=>x.F1,(key,g)=>g.OrderBy(e=>e.F2).First());
Roi roi
la source
2
Cela m'a montré le chemin en utilisant la syntaxe Fluent. Les surcharges de GroupBy semblent vous donner beaucoup de puissance - une à ajouter à la longue liste d'apprentissage!
rogersillito
1
@rogersillito c'est pourquoi on l'appelle une requête (Language Integrated Query - LINQ), le GroupBy a également de nombreuses surcharges, mais il y en a juste quelques-unes qui sont couramment utilisées, cela dépend également de la préférence personnelle, comme certains préfèrent l'écrire comme .GroupBy(x=>x.F1).Select(g=>...), cela peut sembler plus facile à comprendre.
King King
11
Vous devriez remplacer .First()par .FirstOrDefault()ou vous obtiendrez l'exception: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 Je sais à ce sujet, mais j'ai supposé que LINQ ici est utilisé comme LINQ-to-object, pas LINQ-to-entités, afin que nous puissions l'utiliser en toute sécurité .First(). La question de l'OP ressemble vraiment à se soucier simplement de linq-to-object, bien qu'il ait également tagué la question avec linq-to-entities(pas sûr s'il a compris ce que c'est).
King King
1
J'ai aimé cette réponse, belle.
Ajas Aju
8

Le awnser de @Alireza est totalement correct, mais vous devez remarquer que lorsque vous utilisez ce code

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

qui est similaire à ce code parce que vous commandez la liste, puis faites le regroupement pour obtenir la première ligne de groupes

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

Maintenant, si vous voulez faire quelque chose de plus complexe comme prendre le même résultat de regroupement mais prendre le premier élément de F2 et le dernier élément de F3 ou quelque chose de plus personnalisé, vous pouvez le faire en étudiant le code ci-dessous

 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;
           });

Donc, vous obtiendrez quelque chose comme

   F1            F2             F3 
 -----------------------------------
   Nima          1990           12
   John          2001           2
   Sara          2010           4
Stavros Koureas
la source
1
Le délimiteur ou le séparateur du nouvel objet doit être une virgule et non un point-virgule.
Naredla Nithesh Reddy
3

Utilisez-le pour réaliser ce que vous voulez. Ensuite, décidez quelles propriétés vous souhaitez retourner.

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