基于集合集

时间:2017-04-04 14:57:18

标签: c# enums

下午好,

我有一个非常有趣的时间试图说服'yield'关键字以我能理解的方式运作,但不幸的是我运气不好。这是场景:

根据用户的属性,我想查找一组RSS提要地址,并显示来自所有这些提要的七篇最新文章,而不是每个那些饲料。为此,我正在尝试从每个Feed中构建最近五篇文章的集合,然后从这些文章中获取最近的7篇文章。 (非常沉闷的)伪代码类型进程类似于:

  • 查找会员
  • 获取会员的相关属性(组名)
  • 查找该组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为null,或者它的属性为null。我也相信这是解决这个问题的一种非常非常糟糕的方法,但在这种情况下我无法找到使用yield关键字的方向。

我确实找到了this question,但它并没有帮助我理解任何事情。

我正在尝试以这种方式实现,或者我只需要咬紧牙关并使用几个foreach循环?

3 个答案:

答案 0 :(得分:0)

使用asyncawait将RSS Feed加载到内存中,然后按日期排序,只需Take前7个

答案 1 :(得分:0)

考虑到你想要在GetLatestArticlesFromFeed中做的所有事情是获得5个最新项目,是不是更容易只订购一次列表然后采取前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>();
        }          
    }
}

如果这不起作用,请告诉我!

答案 2 :(得分: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,这有助于一切顺利进入的地方。

我觉得有点厚颜无耻回答我自己的问题,但总的来说,我认为这是一个很好的,整洁的建议答案之间的平衡,它肯定似乎功能。我会添加一些强化和评论,当然,如果有人有反馈,我会感激地收到它。

谢谢! 灰