Какая будет оптимизированная версия данного кода? - PullRequest
0 голосов
/ 19 февраля 2011

У меня есть блок кода, где я проверяю флажки, сравнивая содержимое таблицы данных в данном коде:

 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 было бы замечательно.

Ответы [ 4 ]

2 голосов
/ 19 февраля 2011

Реальной оптимизацией будет привязка данных.

1 голос
/ 19 февраля 2011

Это то, что я делаю

 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;
    }
 }

если идентификатор на флажках отличается (это, вероятно, так),

 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;
         }
    }
 }
0 голосов
/ 19 февраля 2011

По сути, вы выполняете операцию JOIN.Существует 3 типа алгоритмов соединения общего пользования - вложенный цикл, хэш и слияние.В вашем коде используется алгоритм вложенных циклов, который кажется подходящим для таблиц размером 10 и 5, если только один или оба уже не отсортированы (в этом случае объединение слиянием может быть более подходящим).

Я могу 'Я не представляю, что это узкое место в любом реальном приложении, но, возможно, мы можем немного улучшить его с некоторыми допущениями.

  1. Давайте начнем с подъема переменных, чтобы они не были пересчитаны(JIT-оптимизатор, вероятно, сделает это автоматически, но это не помешает):
    <code>
     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 является строкой, давайте используем приведение:
    <code>
     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. Поскольку мы никогда не снимаем флажок, и сравнение bool должно быть в среднем быстрее, чем сравнение строк:
    <code>
     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. Предполагая, что каждое значение флажка уникально, мыможет прекратить итерации, когда мы найдем результат:
    <code>
     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 более эффективно:
    <code>
     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:
    <code>
     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;
     }
 }    

Или с каждым расширением:

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

, которое может быть немного медленнее, но много читаетлучше ИМО.

0 голосов
/ 19 февраля 2011

Несмотря на то, что он делает практически то же самое за кулисами, что и ответ @Aristos, выполнение этого, как показано ниже, немного сократит ваши строки кода:

foreach (DataRow dr in dtResult.Rows)
{
    ListItem item = chkboxListWorkTypes.Items.FindByValue(dr["WorkTypeID"].ToString());
    if (item != null)
    {
         item.Selected = true;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...