2013-06-06 5 views
3

У меня есть HashSet, содержащий пользовательские объекты, созданные при чтении двоичного файла. У меня также есть словарь, созданный при чтении каждой строки файла DBF. Есть свойство индекса на обеих этих линиях друг с другом. Например, 10-й пункт в моем словаре будет соответствовать 10-му элементу в моем HashSet.Словарь C# работает медленно при использовании containsValue()

Я сравниваю БОЛЬШИЕ объемы данных друг против друга. Там может быть от 10 000 записей до 500 000. Приложение проверяет два других файла (один двоичный, другой - dbf) для различий. Он проверяет хэш-код объекта (который генерируется определенными свойствами, он делает это сравнение быстро и легко)

Вот как я строить каждый отдельный словарь (есть аналогичный один для мод, а):

foreach (DataRow row in origDbfFile.datatable.Rows) 
{ 
    string str = ""; 
    foreach (String columnName in columnNames) 
    { 
     str += "~" + row.Field<Object>(columnName); 
    } 
    origDRdict.Add(d, str); 
    d++; 
} 

Столбцы между двумя файлами всегда будут одинаковыми. Однако я могу работать в двух разных файлах с разными столбцами. Я по существу выводю все данные в строку поиска словаря. Я только хочу ударить файл DBF снова, если данные разные.

Вот мой код для поиска БД. Это найдет различия, это просто очень медленно, когда он запускает раздел ELSE моего (! FoundIt) if block. Если я удалю его, потребуется всего одна минута, чтобы перечислить все не найденные предметы.

foreach (CustomClass customclass in origCustomClassList) { 
    Boolean foundIt = false; 
    if (modCustomClassList.Contains(customclass)) 
    { 
     foundIt = true; 
    } 
    //at this point, an element has not been found 
    if (!foundIt) 
    { 
     notFoundRecords.Add(customclass); 

    } 
    //If I remove this entire else block, code runs fast. 
    else //at this point an element has been found 
    { 
     // 
     //check 'modified' dictionary array 
     if (!(modDRdict.ContainsValue(origDRdict[i]))) 
     { 
      //at this point, the coordinates are the same, 
      //however there are DB changes 
      //this is where I would do a full check based on indexes 
      //to show changes. 
     } 
    } 

    i++; //since hashsets can't be indexed, we need to increment 
} 

Что я пробовал/Другие мысли

-Generating в HashSet из пользовательских объектов, пользовательский объект, имеющий индекс целого числа, а строка является длина столбцов и значения

-Удаление if (! (ModDRdict.ContainsValue (origDRdict [i]))) делает код значительно быстрее. Время итерации удаленных записей между двумя 440 000 файлами записей занимает всего одну минуту. Словарь поиска навсегда!

-I не думаю, что цикл foreach внутри цикла foreach вызывает слишком много накладных расходов. Если я сохраню его в коде, но не выполняю поиск, он все равно работает быстро.

+12

Словари полезны (то есть быстро), когда вы выполняете ContainsKey не ContainsValue ... – digEmAll

+5

Чтобы расширить, 'ContainsKey' является o (1), а' ContainsValue' - o (n). – Rotem

+0

Вместо Contains вы можете использовать TryGetValue. Это примерно на 40% быстрее, как вы можете видеть в этой [нить] (http://stackoverflow.com/questions/9382681/what-is-more-efficient-dictionary-trygetvalue-or-containskeyitem) –

ответ

2

Словари оптимизированы для поиска по ключевым словам, а не по значению. Если вам нужно искать по значению, вы используете неправильный словарь. Вам нужно будет создать либо HashSet для ваших значений, чтобы быстро проверить наличие сдерживания, либо создать обратный словарь, если вам нужны ключи.

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