8
\$\begingroup\$

I have two Dictionaries with around 65,000 KeyValuePairs each. I used foreach and if-else statements to compare them and get values, but it goes very slow. How could I optimize my code and gain more speed?

private void bgwCompare_DoWork(object sender, DoWorkEventArgs e)
{
    var i = 0;

    foreach (KeyValuePair<string, string> line1 in FirstDictionary)
    {
        foreach (KeyValuePair<string, string> line2 in SecondDictionary)
        {
            if (line1.Key == line2.Key)
            {
                ResultDictionary.TryAdd(line1.Value, line2.Value);

                ListViewItem item = new ListViewItem(line1.Value);
                item.SubItems.Add(line2.Value);

                ResultList.Items.Add(item);
            }

            i++;
            bgwCompare.ReportProgress(i * 100 / (FirstDictionary.Count() * SecondDictionary.Count()));
        }
    }
}
\$\endgroup\$
9
\$\begingroup\$

If I'm understanding it correctly, you're populating a ConcurrentDictionary from the values of two other ConcurrentDictionaries, where the keys are equal.

Try this, it's vastly faster than your loop in my tests.

var matches = FirstDictionary.Keys.Intersect(SecondDictionary.Keys);
foreach (var m in matches)
    ResultDictionary.TryAdd(FirstDictionary[m], SecondDictionary[m]);
\$\endgroup\$
  • \$\begingroup\$ And now I need to go look up the Intersect implementation Im curious how MS optimized it. \$\endgroup\$ – RubberDuck May 1 '16 at 11:43
8
\$\begingroup\$

Put simply you change an \$O(1)\$ operation to a \$O(n)\$ one.

Dictionary's have \$O(1)\$ key lookup and so if you change your inner loop to, SecondDictionary.TryGetValue. It'll achieve the same results without going through every item in SecondDictionary.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.