2012-06-26 6 views
0

Утренние ребята.Улучшить метод повторной проверки

Используя диез .net4 и MS Visual Studio 2010.

Я разработал дублирования проверки моего окна формы программы. Он работает отлично и практически мгновенно на моем Datagrid, когда есть несколько сотен записей.

Проблема, которую я заметил, заключается в том, что при наличии 6000 записей она недостаточно эффективна и занимает минуты.

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

Ваша помощь в очередной раз ценится!

Вот код:

public void CheckForDuplicate() 
{ 
    DataGridViewRowCollection coll = ParetoGrid.Rows; 
    DataGridViewRowCollection colls = ParetoGrid.Rows; 
    IList<String> listParts = new List<String>(); 
    int count = 0; 

    foreach (DataGridViewRow item in coll) 
    { 
     foreach (DataGridViewRow items in colls) 
     { 
      count++; 
      if ((items.Cells["NewPareto"].Value != null) && (items.Cells["NewPareto"].Value != DBNull.Value)) 
      { 
       if ((items.Cells["NewPareto"].Value != DBNull.Value) && (items.Cells["NewPareto"].Value != null) && (items.Cells["NewPareto"].Value.Equals(item.Cells["NewPareto"].Value))) 
       { 
        if ((items.Cells["Part"].Value != DBNull.Value) && (items.Cells["Part"].Value != null) && !(items.Cells["Part"].Value.Equals(item.Cells["Part"].Value))) 
        { 
         listParts.Add(items.Cells["Part"].Value.ToString()); 

         dupi = true; //boolean toggle 
        } 
       } 
      } 
     } 
    } 
    MyErrorGrid.DataSource = listParts.Select(x => new { Part = x }).ToList();  
} 

Любые вопросы, дайте мне знать, и я сделаю все возможное, чтобы ответить на них.

+1

Один простой оптимизация, который не изменит свой код много, не выглядит все столбцы в два раза, внешний контур петли все из них, внутренний контура петли от того, где внешнего контура есть, до конца –

+0

кроме того. Ячейки ["NewPareto"] - это поиск строк. Как насчет того, что вы получите NUMBER один раз за пределами цикла (таблицы не будут меняться в цикле), а затем получить доступ через номер? – TomTom

+0

yer Исходная причина: я зацикливаюсь, чтобы получить 1-е значение, а затем используя его в качестве базы, я проверяю все остальные значения через второй цикл, чтобы увидеть, есть ли совпадение. – lemunk

ответ

1

Если вы можете, вы должны попытаться сделать это на базовых данных, а не на объектах пользовательского интерфейса - однако у меня есть подозрение, что вы высеиваете его из набора DataRows, и в этом случае вы, возможно, не сможете для этого.

Я думаю, что большая часть проблемы здесь заключается в повторном разыменовании ячеек по имени и в том, что вы неоднократно поклоняетесь второму набору ячеек. Так что все впереди:

var first = (from row in coll.Cast<DataGridViewRow>() 
      let newpareto = row.Cells["NewPareto"].Value ?? DBNull.Value 
      let part = row.Cells["Part"].Value ?? DBNull.Value 
      where newpareto != DBNull.Value && part != DBNull.Value 
      select new 
      { newpareto = newpareto, part = part }).ToArray(); 

//identical - so a copy-paste job (if not using anonymous type we could refactor) 
var second = (from row in colls.Cast<DataGridViewRow>() 
      let newpareto = row.Cells["NewPareto"].Value ?? DBNull.Value 
      let part = row.Cells["Part"].Value ?? DBNull.Value 
      where newpareto != DBNull.Value && part != DBNull.Value 
      select new 
      { newpareto = newpareto, part = part }).ToArray(); 


//now produce our list of strings 
var listParts = (from f in first 
       where second.Any(v => v.newpareto.Equals(f.newpareto) 
            && !v.part.Equals(f.part)) 
       select f.part.ToString()).ToList(); //if you want it as a list. 
+0

, чтобы соответствовать указанному коду, это должно быть '&&! Part1.Equals (part2)' –

+0

ok Я проверил некоторое тестирование, 3 раза с моей версией 3 раза с вашей. Основано на 4832 записях, мне требуется 1 мин 21 секунда. Для завершения требуется 57 секунд. Это отличная новость, так как она пропустила приятные 24 секунды времени, но все еще нуждается в улучшении. – lemunk

+0

gona попробуйте ваше новое решение намного быстрее! – lemunk

1

Существует подход, который сделает это намного более эффективным. Вам необходимо вычислить хэш каждого элемента. Элементы с разными хэшами не могут быть дублирующими.

Как только у вас есть хэши, вы можете либо сортировать по хешу, либо использовать структуру данных с эффективным поиском ключей (например,), чтобы найти все дубликаты.

+1

Хотя я бы согласился в принципе - это не тривиальное решение: как вы будете вычислять хэши для тех, у кого есть нулевые значения в ячейках или DBNulls? Если вы примете очевидный подход и используете '0', вы не сможете реализовать короткое замыкание в логике равенства здесь, где любые ячейки с« null »или« DBNull.Value »автоматически игнорируются. Вы в конечном итоге вынуждаете словарь выполнять более длительную проверку равенства для этих строк, потому что они будут использовать один и тот же хэш. –

+0

@AndrasZoltan да, этот алгоритм требует, чтобы вы выполняли проверки некоторых элементов, которые в конечном итоге отличаются друг от друга. Это его фундаментальное свойство. Улучшение по-прежнему огромно, потому что вам больше не нужно сравнивать 6000 * 6000/2. –

+0

Использование хэшей seem очень интересно, хотя я никогда не пытался это сделать раньше, и я немного сомневаюсь в своих навыках, чтобы внедрить его в мой код. – lemunk

Смежные вопросы