2015-05-26 3 views
-1

У меня есть список из 1,5 миллионов записей. Мне нужно перебирать через этот список около 300 раз, чтобы вытащить определенные записи для выполнения вычислений. Я предположил, что преобразование моего списка в словарь . бы мои взгляды вверх быстрее во время итерацииБыстрая итерация словаря (строка, список>

моего список состоит из класса, как это:

class SummaryRecord 
{ 
    public int CalcData { get; set; } 
    public string Id2 { get; set; } 
    public string Id2 { get; set; } 
} 

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

Dictionary<string, SummaryRecord> dictSummaries = summaries.ToDictionary(
    e => e.Id1 + "+" + e.Id2 + "+" + e.CalcData); 

Затем я просматриваю дополнительный список из 300 пар идентификаторов, чтобы вытащить записи из большого списка.

foreach(var ids in listOfIds) 
{ 
    var filteredData = from d in dictSummaries 
         where 
         d.Key.Contains(ids.Id1 + "+" + ids.Id2) 
         select d; 

    //perform operation on filteredData here. This code is slow as well. 
    filteredData.Count() 
} 

Это, очевидно, не очень эффективно на основе того, что я вижу производительности мудры, как она занимает около 1 секунды (раз 300 секунд) для выполнения каждой итерации. Как ускорить процесс запроса записей?

+0

Afaik словарь будет работать лучше на поисковых системах, но не гарантируется, что это делается итерациями ... –

+0

Я ответил ниже. Но я хочу кое-что уточнить. Поскольку я вижу, что вы используете .Count(), ожидаете ли вы, что в словаре с одним и тем же ключом может быть более 1 записи? Потому что это невозможно и вызовет исключение, когда вы попробуете вторую вставку. –

+1

Словарь будет медленнее итерации, чем «Список». Преимущество «Словаря» заключается в том, что, в общем, * вам совсем не нужно его повторять *, когда вы используете его правильно. Каковы * актуальные * требования вашей программы. – Servy

ответ

3

Как вы, на самом деле вы не используете силу словаря. Вы запросите итерацию по каждой записи в словаре, проверяющей условие, которое вы дали.

Поскольку у вас есть полный ключ, вы должны просто сделать прямой поиск каждой клавиши:

string key = ids.Id1 + "+" + ids.Id2; SummaryRecord summaryRecord = dictSummaries[key];

Если вы не уверены в том, что ключ существует, убедитесь, что сделать TryGetValue() вместо или сделать ContainsKey() проверка.

+0

Он видит, содержит ли ключ значение, а не если оно равно значению. – Servy

+0

@Servy Да, но похоже, что он просто злоупотреблял .Contains() и, вероятно, предназначался для использования .Equals(). –

+0

Возможно. Или, может быть, он действительно хочет найти значения, где ключ содержит значение, а не где он равен значению. – Servy

-1

Удовлетворительно вы звоните в String.Contains.
Вы повторяете КАЧЕСТВЕННЫЙ ключ в словаре и проверяете ключ, содержащий другую строку.
Так «prekey1key2» содержит «key1key2.
Если вы намерены получить точный поиск быть в курсе, что это не то, что вы получаете (и вы не используя словарь HashBuckets на всех).

Вы переборе каждую запись Вы не используете поиск по словарю вообще. Хуже того, вы повторяете каждую запись в Словаре для каждой строки в спискеOFIds.

Если ID1 и ID2 образуют уникальный ключ, то используйте это как ключ и посмотрите его прямо как ответ Кевина
Это Хехед поиск и курение быстро

SummaryRecord summaryRecord = dictSummaries[key]; 

Также выбирает ID1, ID2, который хорошо использует хэш.
Не могли бы вы использовать два int16, которые вы можете объединить в Int32?
Вы можете зайти так далеко, чтобы переопределить GetHashCode с помощью реального ключа.
И переопределить равные.

Другой путь в этом

class SummaryRecord 
{ 
    public int CalcData { get; set; } 
    public string Key { get { return Id1 + Id2; } 
    public string Id2 { get; set; } 
    public string Id2 { get; set; } 
} 
private HashSet<String> keyToFind = new HashSet<String>() {"key1","key2"}; 
var filteredData = from d in dictSummaries.where(x => keyToFind.Contains(x.key)); 

, который содержит будет HashBucket поиска.
Вы все еще итерации Словаря, но теперь у вас очень эффективное сравнение.
И преимущество здесь в том, что вы только итерации словаря один раз.
Попробуйте это первым.

+0

Gee Интересно, откуда пришел -1? – Paparazzi

1

Поскольку вы используете 3 поля в качестве ключа для словаря

summaries.ToDictionary ( е => e.Id1 + "+" + e.Id2 + "+" + e.CalcData);

Я считаю, что возможно иметь кратность, id1 + id2. Если это случай, вы можете использовать ToLookup вместо ToDictionary.

var lookup = summaries.ToLookup(e => e.Id1 + "+" + e.Id2); 

, а затем

foreach(var ids in listOfIds) 
{ 
    var filteredData = lookup[ids.Id1 + "+" + ids.Id2]; 

    //perform operation on filteredData here. This code is slow as well. 
    filteredData.Count() 
} 

Теперь, если это не возможно иметь кратные id1 + ID2, почему вы конкатенации id1 + id2 + CalcData?

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