C# 更高效、更可读的嵌套循环

C# 更高效、更可读的嵌套循环,c#,loops,readability,C#,Loops,Readability,我创建了一个算法,它根据与文章属性相关的两个关键字列表来衡量文章列表的相关性 它工作得很好,而且非常高效。。。但这真是一团糟。它的可读性不太好,所以很难辨别出发生了什么 伪代码中的操作如下所示: 循环浏览名为articles(list) 对于每篇文章,循环浏览角色列表中的每个角色(列表) 检查当前文章是否有任何角色(article.roles=List) 如果是,则循环文章中的每个角色,并尝试将文章中的角色与当前循环中的角色相匹配 如果找到匹配项,则增加物品的重量。如果项目上的角色索引和角色列

我创建了一个算法,它根据与文章属性相关的两个关键字列表来衡量文章列表的相关性

它工作得很好,而且非常高效。。。但这真是一团糟。它的可读性不太好,所以很难辨别出发生了什么

伪代码中的操作如下所示:

  • 循环浏览名为articles
    (list)
  • 对于每篇文章,循环浏览角色列表中的每个角色
    (列表)
  • 检查当前文章是否有任何角色
    (article.roles=List)
  • 如果是,则循环文章中的每个角色,并尝试将文章中的角色与当前循环中的角色相匹配
  • 如果找到匹配项,则增加物品的重量。如果项目上的角色索引和角色列表中的角色都是索引0(在主位置),请为两个匹配的主项添加额外的权重
  • 对主题重复,但对主要匹配没有奖励
编写以下代码的更好方法是什么?我不能使用
foreach
,除非在一个或两个地方使用,因为我需要匹配索引以知道在匹配中添加什么值

private static List<Article> WeighArticles(List<Article> articles, List<string> roles, List<string> topics, List<string> industries)
{
    var returnList = new List<Article>();
    for (int currentArticle = 0; currentArticle < articles.Count; currentArticle++)
    {
        for (int currentRole = 0; currentRole < roles.Count; currentRole++)
        {
            if (articles[currentArticle].Roles != null && articles[currentArticle].Roles.Count > 0)
            {
                for (int currentArticleRole = 0; currentArticleRole < articles[currentArticle].Roles.Count; currentArticleRole++)
                {
                    if (articles[currentArticle].Roles[currentArticleRole].ToLower() == roles[currentRole].ToLower())
                    {
                        if (currentArticleRole == 0 && currentRole == 0)
                            articles[currentArticle].Weight += 3;
                        else
                            articles[currentArticle].Weight += 1;
                    }
                }
            }
        }
        for (int currentTopic = 0; currentTopic < topics.Count; currentTopic++)
        {
            if (articles[currentArticle].Topics != null && articles[currentArticle].Topics.Count > 0)
            {
                for (int currentArticleTopic = 0; currentArticleTopic < articles[currentArticle].Topics.Count; currentArticleTopic++)
                {
                    if (articles[currentArticle].Topics[currentArticleTopic].ToLower() == topics[currentTopic].ToLower())
                    {
                        articles[currentArticle].Weight += 0.8;
                    }
                }
            }
        }
        returnList.Add(articles[currentArticle]);
    }

    return returnList;
}

//Article Class stub (unused properties left out)
public class Article
{
    public List<string> Roles { get; set; }
    public List<string> Topics { get; set; }
    public double Weight { get; set; }
}
私有静态列表文章(列表文章、列表角色、列表主题、列表行业)
{
var returnList=新列表();
对于(int currentArticle=0;currentArticle0)
{
对于(int currentArticleRole=0;currentArticleRole0)
{
对于(int currentArticleTopic=0;currentArticleTopic
好的,您的代码中有几个设计缺陷:

1-太程序化了。你需要学会思考如何编写代码来告诉机器“你想要什么”,而不是“怎么做”,这类似于去酒吧,告诉酒保每样东西的确切比例,而不仅仅是要一杯饮料

2-。这意味着要检查
文章[x]。角色!=空值
毫无意义

3-在
列表上迭代并将每个字符串与
其他字符串进行比较也没有意义。改用

4-您正在抓取输入列表中的每一项,并将其输出到新列表中。也是胡说八道。直接返回输入列表或使用
inputList.ToList()

总而言之,这里有一种更惯用的C语言编写代码:

private static List<Article> WeighArticles(List<Article> articles, List<string> roles, List<string> topics, List<string> industries)
{
    var firstRole = roles.FirstOrDefault();

    var firstArticle = articles.FirstOrDefault();

    var firstArticleRole = firstArticle.Roles.FirstOrDefault();

    if (firstArticleRole != null && firstRole != null && 
        firstRole.ToLower() == firstArticleRole.ToLower())
        firstArticle.Weight += 3;

    var remaining = from a in articles.Skip(1)
                    from r in roles.Skip(1)
                    from ar in a.Roles.Skip(1)
                    where ar.ToLower() == r.ToLower()
                    select a;

    foreach (var article in remaining)
        article.Weight += 1;

    var hastopics = from a in articles
                    from t in topics
                    from at in a.Topics
                    where at.ToLower() == t.ToLower()
                    select a;

    foreach (var article in hastopics)
        article.Weight += .8;

    return articles;
} 
私有静态列表文章(列表文章、列表角色、列表主题、列表行业)
{
var firstRole=roles.FirstOrDefault();
var firstArticle=articles.FirstOrDefault();
var firstArticleRole=firstArticle.Roles.FirstOrDefault();
if(firstArticleRole!=null&&firstRole!=null&&
firstRole.ToLower()==firstArticleRole.ToLower())
首件。重量+=3;
var剩余=从文章中的a开始。跳过(1)
从角色中的r。跳过(1)
从a.Roles.Skip中的ar(1)
其中ar.ToLower()==r.ToLower()
选择一个;
foreach(剩余的var条款)
物品重量+=1;
var hastopics=来自文章中的
从t到主题
来自a.主题中的at
其中at.ToLower()==t.ToLower()
选择一个;
foreach(hastopics中的var文章)
物品重量+=.8;
归还物品;
} 

还有更好的编写方法,例如使用
.Take(1)
而不是
.FirstOrDefault()

好的,您的代码中有几个设计缺陷:

1-太程序化了。你需要学会思考如何编写代码来告诉机器“你想要什么”,而不是“怎么做”,这类似于去酒吧,告诉酒保每样东西的确切比例,而不仅仅是要一杯饮料

2-。这意味着要检查
文章[x]。角色!=空值
毫无意义

3-在
列表上迭代并将每个字符串与
其他字符串进行比较也没有意义。改用

4-您正在抓取输入列表中的每一项,并将其输出到新列表中。也是胡说八道。直接返回输入列表或使用
inputList.ToList()创建新列表 foreach(var article in articles)
 {
     article.AddWeights(roles);
     article.AddWeights(topics);
 }
 public double Weight { get; private set; } // probably you don't need setter

 public void AddWeights(IEnumerable<Role> roles)
 {
     const double RoleWeight = 1;
     const double PrimaryRoleWeight = 3;

     if (!roles.Any())
        return;

     if (Roles == null || !Roles.Any())
         return;

     var pirmaryRole = roles.First();
     var comparison = StringComparison.CurrentCultureIgnoreCase;

     if (String.Equals(Roles[0], primaryRole, comparison))
     {
         Weight += PrimaryRoleWeight;
         return;
     }

     foreach(var role in roles)         
        if (Roles.Contains(role, StringComparer.CurrentCultureIgnoreCase))
            Weight += RoleWeight;
 } 
 public void AddWeights(IEnumerable<Topic> topics)
 {
     const double TopicWeight = 0.8;

     if (Topics == null || !Topics.Any() || !topics.Any())
        return;

     foreach(var topic in topics)         
        if (Topics.Contains(topic, StringComparer.CurrentCultureIgnoreCase))
            Weight += TopicWeight;
 }