2010-07-27 10 views
1

Ce que j'ai est une collection nommée HourList qui est composée d'objets Hour. Deux des propriétés d'une heure sont EmployeeId et Hours. Les employés entrent et sortent et un enregistrement d'une heure est créé. Donc, au bout d'une semaine, je reçois un HourList d'objets multi-heures pour plusieurs employés de notre DAO. Il est demandé qu'un rapport soit établi lorsque seuls les employés avec un nombre total d'heures supérieur à un seuil donné sont affichés.Besoin d'aide pour le filtrage Linq en C#

Exemple: Un simple et aplatis HourList

 
Id | Hours 
---------- 
1 | 4.5 
2 | 6.0 
3 | 9.9 
1 | 5.5 
2 | 2.5 

Le seuil est de 10. Dans ce cas, je ne veux un dossiers d'heure de Id 1, depuis ses heures totalisées dépassent 10.

Je sais que je pourrait le faire en créant une nouvelle méthode DAO pour gérer cela lorsque je retourne la HourList initiale. Je peux aussi le faire très inefficacement avec une déclaration foreach. J'essaie de m'améliorer avec Linq et je voudrais voir ce qu'il est possible de faire. Merci pour toute aide à l'avance.

+2

Notez que l'efficacité de foreach et LINQ sont égaux. Les deux appellent l'énumérateur. Mais LINQ a plus de pouvoir expressif. – Abel

+0

@Abel - Cela a du sens. Je voyais ma collection originale, un foreach imbriqué à travers chaque enregistrement d'heure par Id et les résumant. Si le montant total est supérieur au seuil, stockez cet ID et le montant total dans un nouvel objet pour le reporting. Vous avez raison, je cherchais une expression plus expressive dans Linq pour y faire face. S'il n'y a pas de gain d'efficacité, une nouvelle méthode DAO serait peut-être la meilleure. Cependant, je ne connais pas la syntaxe de Linq pour y parvenir même si je le voulais. – TForceDeveloper

+0

La couche DAO est elle-même parfaitement adaptée pour gérer cela avec LINQ, mais je ne connais pas vos stratégies de conception et comment les données sont récupérées, mises en cache, LINQ2SQL ou LINQ2NH sont utilisées etc ... Mais voici d'autres excellentes réponses. – Abel

Répondre

4
var filtered = HourList.GroupBy(h => h.id) 
         .Select(g => new { Id = g.Key, 
              Hours = g.Sum(h => h.Hours) 
             }) 
         .Where(h => h.Hours >= 10); 

Impossible de le tester, mais cela devrait vous aider à le fermer.

+0

oui, exactement le même code que j'ai ... ça marche. –

+0

@Justin et Stan, merci les gars. Ça a l'air de marcher, mais désolé pour la question novice ... qu'est-ce que je fais avec le Var filtré? Il semble que .Select renvoie un IEnumerable >. Comment puis-je l'utiliser? Avons-nous à boucler à nouveau et le stocker dans quelque chose d'autre? – TForceDeveloper

+0

@TForceDeveloper - filtré devrait contenir une collection Enumerable de types anonymes. Le type doit avoir deux propriétés, ID et Hours. –

1
 var hourList = new List<Hour>() 
     { 
      new Hour() { Id = 1, Hours = 4.5M}, 
      new Hour() { Id = 2, Hours = 6M}, 
      new Hour() { Id = 3, Hours = 9.9M}, 
      new Hour() { Id = 1, Hours = 5.5M}, 
      new Hour() { Id = 2, Hours = 2.5M} 
     }; 

     var over10 = hourList.GroupBy(h => h.Id).Select(h => new { Id = h.Key, Sum = h.Sum(s => s.Hours)}).Where(x => x.Sum >= 10); 
2

Voici un exemple rapide qui fait ce que vous recherchez:

class Program 
    { 
     public class HourEntry 
     { 
      public int Id { get; set; } 
      public int Hours { get; set; } 
     } 

     static void Main(string[] args) 
     { 
      List<HourEntry> hours = new List<HourEntry> 
      { 
       new HourEntry { Id = 1, Hours = 3 }, 
       new HourEntry { Id = 2, Hours = 4 }, 
       new HourEntry { Id = 3, Hours = 3 }, 
       new HourEntry { Id = 1, Hours = 8 }, 
       new HourEntry { Id = 5, Hours = 2 }, 
       new HourEntry { Id = 3, Hours = 2 }, 
       new HourEntry { Id = 3, Hours = 6 }, 
       new HourEntry { Id = 9, Hours = 2 }, 
       new HourEntry { Id = 4, Hours = 2 }, 
      }; 


      var moreThanTen = from h in hours 
           group h by h.Id into hGroup 
           where hGroup.Sum(hg => hg.Hours) > 10 
           select hGroup.Key; 

      foreach (var m in moreThanTen) 
      { 
       Console.WriteLine(m); 
      } 
     } 
    } 
+0

+1 excellent, d'une manière ou d'une autre j'ai essayé de le résoudre de la même manière, mais je me suis perdu en retournant l'objet original (mais l'OP a demandé des ID seulement). Je préfère toujours cette syntaxe fluide ci-dessus :) – Abel

Questions connexes