遍历两个C#列表的最有效方法

时间:2018-11-14 22:47:13

标签: c#

我有一个称为CalculatePopularityScore的方法。它存在于Story对象上。 Story对象具有一个字段,该字段是Comment对象的ICollection。

public virtual ICollection<Comment> Comments { get; set; }

Comment对象具有Reply对象的另一个集合。

我的方法着眼于故事,循环浏览与该故事相关的评论,如果该故事的评论得到回复,则将总数加起来。这样,再加上其他一些领域,就使我有了一个非常(而且我对此很强调)非常简单的故事受欢迎度算法。

public double CalculateStoryPopularityScore()
{
            if (Comments == null) throw new ArgumentException("Comments can't be null");
            if (Comments.Count < 0) throw new ArgumentException("Comments can't be less than zero.");

            int ReplyCountSum = 0;
            double ReplyScore;
            double CommentScore;
            double InsightfulVoteScore;
            double UsefulVoteScore;
            double viewCount;

            foreach (var comment in Comments)
            {
                int replyCount;

                if (comment.Replies == null)
                {
                    throw new ArgumentNullException("Replies cannot be null");
                }

                if (comment.Replies.Count() == 0)
                {
                    replyCount = 0;
                } else
                {
                    replyCount = comment.Replies.Count();
                }

                ReplyCountSum += replyCount;
            }

            ReplyScore = ReplyCountSum * 4;
            CommentScore = Comments.Count() * 4;
            InsightfulVoteScore = InsightFulVoteCount * 3;
            UsefulVoteScore = UsefulVoteCount * 2;
            viewCount = ViewCount;

            double PopularityScore = CommentScore + ReplyScore + InsightfulVoteScore + + UsefulVoteScore + viewCount;
            return PopularityScore;
}

这似乎很好。现在,我想做的就是采用这种方法,并将其应用于多个故事(即列表)。

我目前已编写此方法。它尚未实现另一个循环来浏览对故事的评论集合的答复。我知道嵌套循环被认为是不好而且很慢。查看故事列表,然后查看每个故事中的评论列表,将这些答复加起来,然后计算故事的受欢迎程度得分,最有效的方法是什么?

public void CalculateStoryPopularityScore(List<Story> stories)
{
            if (stories == null) throw new ArgumentException("Stories can't be null");

            double CommentScore;
            double InsightfulVoteScore;
            double UsefulVoteScore;
            double PopularityScore;
            double ViewCount;

            foreach (var story in stories)
            {
                CommentScore = story.Comments.Count() * 4;
                InsightfulVoteScore = story.InsightFulVoteCount * 3;
                UsefulVoteScore = story.UsefulVoteCount * 2;
                ViewCount = story.ViewCount;

                PopularityScore = CommentScore + InsightfulVoteScore + UsefulVoteScore + ViewCount;
                story.PopularityScore = PopularityScore;
            }
}

2 个答案:

答案 0 :(得分:0)

使用SelectMany

var commentCount = story.Comments.Count();

// count all replies to all comments for a story
var replyCountSum = story.Comments
    .SelectMany(c => c.Replies)
    .Count();

应用于故事集:

stories.Select(s => new
{
    Story = s,
    CommentCount = s.Comments.Count(),
    ReplyCount = s.Comments.SelectMany(c => c.Replies).Count(),
});

答案 1 :(得分:0)

除非我丢失了某些内容,否则您使用单独方法计算的所有分数都可以写为Story类的公共只读(计算)属性。可以通过使用SelectMany(用于将列表的列表扁平化为单个列表)然后获得Count属性来获得回复计数:

public class Story
{
    public List<Comment> Comments { get; set; }
    public int InsightFulVoteCount { get; set; }
    public int UsefulVoteCount { get; set; }
    public int ViewCount { get; set; }

    public int PopularityScore
    {
        get
        {
            return
                (Comments?.Count ?? 0) * 4 +
                (Comments?.SelectMany(comment => comment.Replies).Count() ?? 0) * 4 +
                InsightFulVoteCount * 3 +
                UsefulVoteCount * 2 +
                ViewCount;
        }
    }
}

public class Comment
{
    public List<string> Replies { get; set; }
}

如果您不熟悉null-conditional运算符(?.),则在访问右操作数(属性)之前,如果左操作数(对象)为null,它将返回null或对象的方法)。如果左侧不为null,则返回属性/方法值。

然后null-coalescing operator??)评估左操作数(这是属性或方法访问的结果),如果为空,则返回右操作数('0'就我们而言)。

基本上,这简化了代码。您不必这样做:

var score = 0;
if (Comments != null) score = Comments.Count;

您可以这样做:

var score = Comments?.Count ?? 0;