【问题标题】:What will be optimized version of the given code?给定代码的优化版本是什么?
【发布时间】:2011-02-19 13:23:14
【问题描述】:

我有一个代码块,我在其中检查复选框,比较给定代码中数据表的内容:

 foreach (DataRow dr in dtResult.Rows)
 {
    for (var i = 0; i < chkboxListWorkTypes.Items.Count; i++)
    {
      if (chkboxListWorkTypes.Items[i].Value.Equals(dr["WorkTypeID"].ToString()))
      {
         chkboxListWorkTypes.Items[i].Selected = true;
      }
    }
 }

任何 labmda 或 linq 表达式都会很棒。

【问题讨论】:

  • 如何优化?表现?代码质量?还有什么?
  • 你试过使用数据绑定吗?
  • 任何专业开发人员都可以查看代码并说出需要哪种类型的优化。如果您在数据表中有 10 行和 5 个复选框,那么根据上面的代码,它将迭代 50 次以获得实际结果。很明显,我需要性能,通过 LINQ 或 LAMBDA。
  • > 我需要性能,通过 LINQ 或 LAMBDA。实际上,如果您需要性能,LINQ 是不可行的。
  • “LINQ 不是魔法”阿门。如果你想减少迭代,你需要一个不同的算法——但根据要求,可能没有办法绕过它。 我们无法猜测还有什么其他方法可能有效。最多,我们可以尝试改进常数因子 - 但看起来没有太多工作要做。

标签: c# asp.net linq lambda checkbox


【解决方案1】:

真正的优化将是数据绑定。

【讨论】:

  • 任何其他方式...通过 LINQ 或 LAMBDA
  • 当然,这段代码可以使用 LINQ 部分重写,但这不是优化
  • 好的,好的。但无论如何,为了尽量减少这些迭代,据我在代码中看到的,我无法进行绑定。
  • 是否可以在“for循环内部和if条件”中使用一些lambda表达式
【解决方案2】:

这就是我的工作

 foreach (DataRow dr in dtResult.Rows)
 {
    string cWorkTypeID = dr["WorkTypeID"].ToString();
    for (var i = 0; i < chkboxListWorkTypes.Items.Count; i++)
    {
         if(chkboxListWorkTypes.Items[i].Value.Equals(cWorkTypeID))
           chkboxListWorkTypes.Items[i].Selected =true;
    }
 }

如果复选框上的 ID 不同(可能是),

 foreach (DataRow dr in dtResult.Rows)
 {
    string cWorkTypeID = dr["WorkTypeID"].ToString();
    for (var i = 0; i < chkboxListWorkTypes.Items.Count; i++)
    {
         if(chkboxListWorkTypes.Items[i].Value.Equals(cWorkTypeID))
         {
            chkboxListWorkTypes.Items[i].Selected = true;
            break;
         }
    }
 }

【讨论】:

    【解决方案3】:

    虽然它在幕后做的事情与@Aristos 的回答几乎一样,但像下面这样做会减少你的代码行数:

    foreach (DataRow dr in dtResult.Rows)
    {
        ListItem item = chkboxListWorkTypes.Items.FindByValue(dr["WorkTypeID"].ToString());
        if (item != null)
        {
             item.Selected = true;
        }
    }
    

    【讨论】:

      【解决方案4】:

      您实际上是在执行 JOIN 操作。常用的有3 types of join algorithms——嵌套循环、散列和合并。您的代码正在使用嵌套循环算法 - 这似乎适用于 10 和 5 的表大小,除非其中一个或两个已经排序(在这种情况下,合并连接可能更合适)。

      我无法想象这会成为任何实际应用程序的瓶颈 - 但是,我们可以通过一些假设对其进行一些改进。

      1. 让我们从提升变量开始,以确保它们不会被重新计算(JIT 优化器可能会自动执行此操作,但不会造成伤害):
        
         int chkBoxCount = chkboxListWorkTypes.Items.Count;
         foreach (DataRow dr in dtResult.Rows)
         {
            string rowValue = dr["WorkTypeID"].ToString();
            for (var i = 0; i < chkBoxCount; i++)
            {
              var chkBox = chkboxListWorkTypes.Items[i];
              if (chkBox.Value.Equals(rowValue))
              {
                 chkBox.Selected = true;
              }
            }
         }
        
      2. 假设 rowValue 是一个字符串,让我们使用强制转换:
        
         int chkBoxCount = chkboxListWorkTypes.Items.Count;
         foreach (DataRow dr in dtResult.Rows)
         {
            string rowValue = (string)dr["WorkTypeID"];
            for (var i = 0; i < chkBoxCount; i++)
            {
              var chkBox = chkboxListWorkTypes.Items[i];
              if (chkBox.Value.Equals(rowValue))
              {
                 chkBox.Selected = true;
              }
            }
         }
        
      3. 由于我们从不取消选中复选框,并且平均而言,布尔比较应该比字符串比较快:
        
         int chkBoxCount = chkboxListWorkTypes.Items.Count;
         foreach (DataRow dr in dtResult.Rows)
         {
            string rowValue = (string)dr["WorkTypeID"];
            for (var i = 0; i < chkBoxCount; i++)
            {
              var chkBox = chkboxListWorkTypes.Items[i];
              if (!chkBox.Selected && chkBox.Value.Equals(rowValue)) 
              {
                 chkBox.Selected = true;
              }
            }
         }
        
      4. 假设每个复选框的值都是唯一的,我们可以在找到结果时停止迭代:
        
         int chkBoxCount = chkboxListWorkTypes.Items.Count;
         foreach (DataRow dr in dtResult.Rows)
         {
            string rowValue = (string)dr["WorkTypeID"];
            for (var i = 0; i < chkBoxCount; i++)
            {
              var chkBox = chkboxListWorkTypes.Items[i];
              if (!chkBox.Selected && chkBox.Value.Equals(rowValue)) 
              {
                 chkBox.Selected = true;
                 break; // stop looking
              }
            }
         }
        
      5. 由于您有 10 行和 5 个复选框 - 我们应该反转循环。由于我们在找到值时中断内部循环,因此使内部循环大于 2 更有效:
        
         int chkBoxCount = chkboxListWorkTypes.Items.Count;
         for (var i = 0; i < chkBoxCount; i++)
         {
           var chkBox = chkboxListWorkTypes.Items[i];
           if (chkBox.Selected) continue;
           foreach (DataRow dr in dtResult.Rows)
           {
              string rowValue = (string)dr["WorkTypeID"];
              if (chkBox.Value.Equals(rowValue)) 
              {
                 chkBox.Selected = true;
                 break;
              }
           }
         }
        
      6. 假设您不关心文化或区分大小写的比较,我们可以使用 OrdinalIgnoreCase:
        
         int chkBoxCount = chkboxListWorkTypes.Items.Count;
         for (var i = 0; i < chkBoxCount; i++)
         {
           var chkBox = chkboxListWorkTypes.Items[i];
           if (chkBox.Selected) continue;
           foreach (DataRow dr in dtResult.Rows)
           {
              string rowValue = (string)dr["WorkTypeID"];
              if (string.Equals(chkBox.Value, rowValue, StringComparison.OrdinalIgnoreCase)) 
              {
                 chkBox.Selected = true;
                 break;
              }
           }
         }
        

      这是我能做的最好的事情。如果在这么小的数据集上有任何可测量的差异,我会感到惊讶。所以,这是你应该真正做的:

       var workTypeIds = dtResult.Rows.Cast<DataRow>().Select(dr => (string)dr["WorkTypeId"]);
       foreach (var chk in chkBoxListWorkTypes) 
       {
           if (workTypeIds.Contains(chk.Value))
           {
              chk.Selected = true;
           }
       }    
      

      或者,使用 Each 扩展:

       var workTypeIds = dtResult.Rows.Cast<DataRow>().Select(dr => (string)dr["WorkTypeId"]);
       chkBoxListWorkTypes.Where(c => workTypeIds.Contains(c.Value)).Each(c => c.Selected = true);
      

      这可能会稍微慢一些,但 IMO 读起来要好得多。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-11-01
        • 1970-01-01
        • 2012-01-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多