2010-12-15 27 views
0

J'ai créé ce qui suit pour expliquer mon problème.Pourriez-vous m'aider à filtrer une collection et en créer une autre dans linq

Compte tenu d'une liste avec PayDates et des périodes. J'ai besoin de créer une nouvelle liste contenant 1 article pour chaque période qui est la plus proche de sa date de paie.

Donc, étant donné l'exemple la liste devrait revenir 2 articles « 1er du mois » et « 17 du mois », comme ils sont les plus proches de leur paydate dans leur période

des suggestions?

private static List<Schedule> GetFilteredScheduleList() 
    { 
    List<Schedule>oldScheduleList=new List<Schedule>(); 
    oldScheduleList.Add(new Schedule { PayDate = new DateTime(2011, 1, 1), Id = 1, Name = "1st of the month", Period = SchedulePeriod.Monthly }); 
    oldScheduleList.Add(new Schedule { PayDate = new DateTime(2011, 1, 4), Id = 1, Name = "4th of the month", Period = SchedulePeriod.Monthly }); 
    oldScheduleList.Add(new Schedule { PayDate = new DateTime(2011, 1, 19), Id = 1, Name = "19th of the month", Period = SchedulePeriod.Monthly }); 
    oldScheduleList.Add(new Schedule { PayDate = new DateTime(2012, 1, 3), Id = 1, Name = "3rd of each quarter", Period = SchedulePeriod.Quarterly }); 
    oldScheduleList.Add(new Schedule { PayDate = new DateTime(2013, 1, 8), Id = 1, Name = "8th each quarter", Period = SchedulePeriod.Quarterly }); 
    oldScheduleList.Add(new Schedule { PayDate = new DateTime(2011, 1, 17), Id = 1, Name = "17th of the month", Period = SchedulePeriod.Quarterly }); 

    // Need to create a new list containing 1 item for each period that is nearest to its Pay Date.Starting point it's today's date. 
    // so the list should return 2 items "1st of the month" and "17th of the month" as they are the closest to their paydate in their period 

    List<Schedule> newScheduleList = oldScheduleList.Where(x=>x.PayDate) 
    } 

Répondre

4

Cela devrait sélectionner l'élément Schedule de chaque période qui est plus proche de maintenant. Est-ce que c'est ce que vous vouliez dire?

oldScheduleList 
    .GroupBy(s => s.Period) 
    .Select(
     g => g 
       .OrderBy(s => Math.Abs((s.PayDate - DateTime.Now).TotalSeconds)) 
       .First() 
    ) 

Edit:

En réponse à votre commentaire, pour obtenir le premier élément pour la période est un peu plus simple. J'ai commenté une clause Where. Cela se la première période à partir de maintenant (c.-à-dates qui ont expiré sont ignorées)

oldScheduleList 
    .GroupBy(s => s.Period) 
    .Select(
     g => g 
       //.Where(s => s.Paydate >= DateTime.Now) //filter expired dates 
       .OrderBy(s => s.PayDate) 
       .First() 
    ) 
+0

Merci pour votre reply.That works.What à propos de simplement comparer les dates dans le délai et obtenir le first.That est vraiment ce Je suis après.Désolé pour ne pas expliquer correctement et merci pour votre aide – user9969

+0

fantastique tous les travaux. Merci! Si vous avez le temps, expliquez ce que math.abs fait dans votre première réponse. Encore merci – user9969

+0

Math.Abs ​​donne la valeur absolue de son seul paramètre. Sa logique est la suivante: Pour une valeur x, si x <0 return -x else retourne x. Par conséquent, il a pour effet de dépouiller le signe négatif des nombres négatifs. Nous pouvons l'utiliser pour obtenir l'ampleur de la différence entre deux valeurs. Par exemple 2 et 4 ont une différence de 2. Nous pouvons calculer ceci comme suit: Math.Abs ​​(2-4) ou Math.Abs ​​(4-2), dans les deux cas la réponse est 2. – spender