2013-10-24 3 views
2

У меня есть программа ниже:передовые группировки и агрегации с помощью LINQ

void Main() 
{ 



List<Online_video_for_programmers> current_year_videos = new List<Online_video_for_programmers>() 
    { 
    new Online_video_for_programmers 
     { 
     video_name="websocket for fortran programmers", 
     season=2, 
     seasontype=1, 
     year=2012 
     }, 
     new Online_video_for_programmers 
     { 
     video_name="cross site scripting for facebook addicts", 
     season=3, 
     seasontype=2, 
     year=2012 
     }, 

     new Online_video_for_programmers 
     { 
     video_name="Artificial intelligence for self aware robots", 
     season=1, 
     seasontype=1, 
     year=2012 
     } 
     , 
     new Online_video_for_programmers 
     { 
     video_name="Artificial intelligence for self aware robots", 
     season=3, 
     seasontype=1, 
     year=2012 
     }, 

     new Online_video_for_programmers 
     { 
     video_name="Artificial intelligence for adavanced robots", 
     season=5, 
     seasontype=1, 
     year=2012 
     }, 
    new Online_video_for_programmers 
     { 
     video_name="Yoga for programmers", 
     season=2, 
     seasontype=2, 
     year=2012 
     }, 
     new Online_video_for_programmers 
     { 
     video_name="Yoga for programmers", 
     season=3, 
     seasontype=2, 
     year=2012 
     } 


    }; 

    //Last years videos sold 

List<Online_video_for_programmers> last_year_videos = new List<Online_video_for_programmers>() 
    { 
    new Online_video_for_programmers 
     { 
     video_name="websocket for fortran programmers", 
     season=2, 
     seasontype=1, 
     year=2011, 
     }, 
     new Online_video_for_programmers 
     { 
     video_name="cross site scripting for facebook addicts", 
     season=3, 
     seasontype=1, 
     year=2011, 
     }, 

     new Online_video_for_programmers 
     { 
     video_name="Artificial intelligence for self aware robots", 
     season=2011, 
     seasontype=3, 
     year=2011, 
     } 
     , 

    new Online_video_for_programmers 
     { 
     video_name="Yoga for programmers", 
     season=4, 
     seasontype=2, 
     year=2011, 
     }, 
      new Online_video_for_programmers 
     { 
     video_name="Yoga for programmers", 
     season=2, 
     seasontype=2, 
     year=2011 
     } 

}; 
} 
// Define other methods and classes here 





public class Online_video_for_programmers 
    { 
    public int seasontype {get;set;} //this can be the id of a year, a quater or month Tyepes are 1: months, 2, for quarters, 3 for year 
public int season {get;set;} // when season type is 1, season =1 means january. 
    //When season type is 2, season=3 means 3rd quater. When seasontype is 3, season =2011 or 2010 etc... 
     public string video_name {get;set;} //The nambe of the video 
     public int year {get;set;} // The year the video was published 
} 

Я хотел бы использовать current_year_videos и last_year_videos, чтобы извлечь какие названия, где опубликованы в прошлом году и не в этом году. Для этого я использую следующий код:

var result=current_year_videos.Concat(last_year_videos).GroupBy(g=> new { seasontype,season,video_name }).Select(s=> new Online_video_for_programmers{ seasontype=s.Key.seasontype, season=s.Key.season, video_name=s.Key.video_name }); 

Код выше дает мне те, которые были произведены как в этом году и в прошлом году, так что я могу легко найти недостающие из них.

И вот в чем проблема. Видеоролик «Искусственный интеллект для самопознающего робота» был выпущен в течение всего года в 2011 году, в то время как в 2012 году было 3 ежемесячных производства. Я не хочу видеть это как отсутствующее в 2012 году. Его следует пропустить только в том случае, если он не был выпущен вообще в 2012 году. Вопрос в том, как настроить мой запрос, чтобы включить это условие в результат. Я потратил некоторое время на то, чтобы понять разные вещи без успеха.

Надеюсь, кто-то может помочь.

Большое спасибо заранее

ответ

3
var result = 
    last_year_videos 
     .Select(v => new { v.video_name, v.season }) 
     .Except(current_year_videos.Select(v => new { v.video_name, v.season })); 

Дает:

{ video_name = "Artificial intelligence for self aware robots", season = 2011 } 
{ video_name = "Yoga for programmers", season = 4 } 

UPDATE: Если вы хотите иметь дело с типом сезона (месяц, квартал, год) при проверке видео, то вы можете создать метод который преобразует тип сезона и сезона в список месяцев:

private static IEnumerable<int> GetMonths(Online_video_for_programmers video) 
{ 
    switch (video.seasontype) 
    { 
     case 1: return Enumerable.Range(video.season, 1); 
     case 2: return Enumerable.Range((video.season - 1) * 3 + 1, 3); 
     case 3: return Enumerable.Range(1, 12); 
     default: 
      throw new ArgumentException("Unknown season type"); 
    } 
} 

С помощью этого метода вы можете проверить, имеет месяцы перекрестки с тем же видео с текущего года:

var currentVideos = 
    current_year_videos.Select(c => new { c.video_name, months = GetMonths(c) }); 

var result = from v in last_year_videos 
      let months = GetMonths(v) 
      where !currentVideos.Any(cv => 
         cv.video_name == v.video_name && 
         months.Intersect(cv.months).Any()) 
      select v.video_name; 

возвраты:

"cross site scripting for facebook addicts" // Month 3 
"Yoga for programmers" // Months 9,10,11 
+1

Это выглядит блестяще ... Я дам ему попробовать. Большое спасибо. –

+0

Уважаемый Лазыберовский, есть проблема с этим кодом. Он не должен сообщать «Искусственный интеллект для самопознающих роботов» как отсутствующий. Он был выпущен в 2011 году. Его следует указывать только как отсутствующий, если он вообще не был произведен. –

+0

@MeelfanBmfp nope, в 2012 году он имеет сезоны '1,3,5'. Но в 2011 году сезон назывался '2011', таким образом, это другое видео, и оно отображается в результатах. Может быть, у вас есть опечатка в ваших данных образца? –

0

Вы хотите найти:

, что названия, где опубликовано в прошлом году, а не в этом году

но для этого, нет необходимости в группировке:

var result = last_year_videos 
    .Where(vLast => !current_year_videos 
     .Select(vCurrent => vCurrent.video_name).Contains(vLast.video_name)); 

Все, что вам нужно сделать, это проверить, существует ли видео с выбранным ключом (video_name) в коллекции прошлого года.

+0

Проверьте имена. Все есть в прошлогодней коллекции –

+0

Согласен. Несмотря на это, на мой взгляд, это решение проблемы. –

+0

Даже если вы замените video_name анонимным объектом, ваш запрос очень неэффективен - он выполняет проектирование видео в текущем году и выполняет поиск * каждого * видео в списке списка. –

Смежные вопросы