2017-04-04 95 views
0

下午好集合構建一個IEnumerable,基於集合

我有一個非常有趣的時間,試圖說服「產量」關鍵字的方式,我能理解的功能,但遺憾的是我沒有太多的運氣。這裏的情景:

基於用戶的財產,我想查找一組RSS源地址和那些飼料的所有,不每個這些飼料顯示最近七次的文章。爲此,我試圖從每個Feed中構建最近五篇文章的集合,然後從這些文章中選取最近的七篇文章。 (非常沉悶)僞碼型過程進行類似:

  • 中查找成員
  • 獲取該成員的有關財產(一組名字)
  • 查找的地址RSS源爲該組
  • 對於集合中的每個地址,得到的五個最新的文章,並放置在另一個集合
  • 採取從 隨後收集最近七次的文章,並顯示它們。

我做了一些研究,已經能夠生產以下:

public static class RSSHelper 
{ 
    public static IEnumerable<SyndicationItem> GetLatestArticlesFromFeeds(List<string> feedList, short articlesToTake) 
    { 
     foreach (string Feed in feedList) 
     { 
      yield return GetLatestArticlesFromFeed(Feed).OrderByDescending(o => o.PublishDate).Take(articlesToTake).First(); 
     } 

     yield return null; 
    } 

    private static IEnumerable<SyndicationItem> GetLatestArticlesFromFeed(string feedURL) 
    { 
     // We're only accepting XML based feeds, so create an XML reader: 
     SyndicationItem Result = new SyndicationItem(); 
     int SkipCount = 0; 

     for (int Curr = 1; Curr <= 5; Curr++) 
     { 
      try 
      { 
       XmlReader Reader = XmlReader.Create(feedURL); 
       SyndicationFeed Feed = SyndicationFeed.Load(Reader); 
       Reader.Close(); 

       Result = Feed.Items.OrderByDescending(o => o.PublishDate).Skip(SkipCount).Take(1).Single(); 
       SkipCount++; 
      } 
      catch (Exception ex) 
      { 
       // Do nothing, else the Yield will fail. 
      } 

      yield return Result; 
     } 
    } 
} 

什麼似乎發生的事情是,我得到五個結果(articlesToTake是7,而不是5),偶爾要麼整個SyndicationItem爲空,或者它的屬性爲空。我也確信這是一個解決這個問題的非常非常不好的方法,但是在這種情況下我找不到使用yield關鍵字的很多方向。

我確實找到了this question,但這並不能幫助我理解任何東西。

正在嘗試以這種方式達到目的嗎?還是我只需要咬緊牙關並使用幾個foreach循環?

+0

「偶爾或者整個SyndicationItem爲空」那麼,你做'產出返回null;'......你期望發生什麼? – NPSF3000

+0

@ NPSF3000它*應該是無法訪問的代碼,因爲FeedList中總是有一個字符串。當然,檢查會更合適,但是在工作時我會加強檢查。 – Ashilta

+0

所以在feedlist中有一個字符串,並且一旦處理完它就會返回到下一個返回null的語句。這是非常可達的代碼。 – NPSF3000

回答

0

早上,

現在,我不覺得死亡熱身,我已經工作了!感謝@Rodrigo和@McKabue在尋找最終答案時的幫助,以及@ NPSF3000指出我原來的愚蠢!

我已經對這個解決結果:

public static class RSSHelper 
{ 
    public static IEnumerable<SyndicationItem> GetLatestArticlesFromFeeds(List<string> feedList, short articlesToTake) 
    { 
     return GetLatestArticlesFromFeedsAsync(feedList, articlesToTake).Result; 
    } 

    private async static Task<IEnumerable<SyndicationItem>> GetLatestArticlesFromFeedsAsync(List<string> feedList, short articlesToTake) 
    { 
     List<Task<IEnumerable<SyndicationItem>>> TaskList = new List<Task<IEnumerable<SyndicationItem>>>(); 
     foreach (string Feed in feedList) 
     { 
      // Call and start a task to evaluate the RSS feeds 
      Task<IEnumerable<SyndicationItem>> T = Task.FromResult(GetLatestArticlesFromFeed(Feed).Result); 
      TaskList.Add(T); 
     } 

     var Results = await Task.WhenAll(TaskList); 

     // Filter the not null results - on the balance of probabilities, we'll still get more than 7 results. 
     var ReturnList = Results.SelectMany(s => TaskList.Where(w => w.Result != null).SelectMany(z => z.Result).OrderByDescending(o => o.PublishDate)).Take(articlesToTake); 
     return ReturnList; 
    } 

    private async static Task<IEnumerable<SyndicationItem>> GetLatestArticlesFromFeed(string feedURL) 
    { 
     // We're only accepting XML based feeds, so create an XML reader: 
     try 
     { 
      XmlReader Reader = XmlReader.Create(feedURL); 
      SyndicationFeed Feed = SyndicationFeed.Load(Reader); 
      Reader.Close(); 

      return Feed.Items.OrderByDescending(o => o.PublishDate).Take(5); 
     } 
     catch (Exception ex) 
     { 
      return null; 
     } 
    } 
} 

我花了一段時間來繞到我的頭,我幾乎忘了定義,我拉開任務的結果類型,但幸運的是,我今天早上偶然發現了this question,這幫助一切都很好地落實到位。

回答我自己的問題,我覺得有點厚臉皮,但總的來說,我認爲這是建議的答案之間的一個不錯的,整潔的平衡,它似乎功能。我會添加一些強化和評論,當然如果任何人有反饋,我會感激地收到它。

謝謝! 灰

0

加載使用asyncawait記憶了RSS提要,然後按日期排序他們,只是Take第7

+0

我同意這是一個更高性能的解決方案,但是我仍然試圖比較五個結果集合。目的是要有一個集合,以便我可以在一組記錄上執行OrderByDescending。我想我的問題中缺少的一點是如何將五個集合合併爲一個IEnumerable,然後允許記錄的排序/獲取。 – Ashilta

+0

'我把五個集合合併成一個IEnumerable'SelectMany。 – NPSF3000

+0

使用SelectMany https://msdn.microsoft.com/en-us/library/bb534336(v=vs.110).aspx – McKabue

0

考慮到所有你想在GetLatestArticlesFromFeed做的是讓5個最新資料,也不會只列出一次,然後再拿出前五個項目更容易一些?它看起來像這樣(連同基於SelectMany方法的第一種方法)

public static class RSSHelper 
{ 
    public static IEnumerable<SyndicationItem> GetLatestArticlesFromFeeds(List<string> feedList, short articlesToTake) 
    { 
     return feedList.SelectMany(f => GetLatestArticlesFromFeed(f)).OrderByDescending(a => a.PublishDate).Take(articlesToTake); 
    } 

    private static IEnumerable<SyndicationItem> GetLatestArticlesFromFeed(string feedURL) 
    { 
     // We're only accepting XML based feeds, so create an XML reader: 

     SyndicationFeed feed = null; 

     try 
     { 
      using (XmlReader reader = XmlReader.Create(feedURL)) 
      { 
       feed = SyndicationFeed.Load(reader); 
      } 

      return feed.Items.OrderByDescending(o => o.PublishDate).Take(5); 
     } 
     catch 
     { 
      return Enumerable.Empty<SyndicationItem>(); 
     }   
    } 
} 

讓我知道這是行不通的!

+0

感謝羅德里戈,但它並不完美,但我不認爲這是你的錯。我使用的XML提要之一是,我懷疑,以非預期格式編碼,這會導致引發一個有趣的異常。因此我得到一些空引用異常,即使在SelectMany謂詞之後放置了一個保存導航操作符。我會繼續修補,但我認爲在這和麥克布伊的答案之間我應該能夠接近。 – Ashilta

+0

當您調用SyndicationFeed.Load時會發生此錯誤嗎?你可以用try..catch語句嘗試圍繞它,如果發生異常,則返回一個Enumerable.Empty