Zoltán Barna
Zoltán Barna

Reputation: 493

firstorDefault performance rising

part of the code:

Dictionary<Calculation, List<PropertyValue>> result = new Dictionary<Calculation, List<PropertyValue>>();
while (reader != null && reader.Read()) //it loops about 60000, and it will be bigger
{
    #region create calc and propvalue variables
    //...
    #endregion

    //this FirstOrDefault needs a lot of time
    tmpElementOfResult = result.Keys.FirstOrDefault(r => r.InnerID == calc.InnerID);
    if (tmpElementOfResult == null)
    {
        result.Add(calc, new List<PropertyValue> { propValue });
    }
    else
    {
        result[tmpElementOfResult].Add(propValue);
    }
}

Could you give me some idea how to make it faster, because now it's approximately 25 sec :( ?

Upvotes: 1

Views: 2454

Answers (3)

Jon Skeet
Jon Skeet

Reputation: 1504172

It sounds like you should have a dictionary from the type of calc.InnerID, instead of a Dictionary<Calc, ...>. That way you can do the lookup far more quickly. Do you actually need to store the Calc itself at all, or are you only interested in the ID?

For example:

Dictionary<Guid, List<PropertyValue>> result = 
    new Dictionary<Guid, List<PropertyValue>>();
while (reader.Read())
{
    // Work out calc
    List<PropertyValue> list;
    if (!result.TryGetValue(calc.InnerID, out list))
    {
         list = new List<PropertyValue>();
         result[calc.InnerID] = list;
    }
    list.Add(propValue);
}

Alternatively, if you can convert the reader to an IEnumerable<Calc> you could use:

Lookup<Guid, PropertyValue> result = items.ToLookup(x => x.InnerID,
                                                    // Or however you get it...
                                                    x => x.PropertyValue);

EDIT: It sounds like two Calc values should be deemed equal if they have the same InnerID, right? So override Equals and GetHashCode within Calc to refer to the InnerID. Then you can just use:

Lookup<Calc, PropertyValue> result = items.ToLookup(x => x,
                                                    // Or however you get it...
                                                    x => x.PropertyValue);

... or you can use code like the first snippet, but with a Dictionary<Calc, ...>:

Dictionary<Calc, List<PropertyValue>> result = 
    new Dictionary<Calc, List<PropertyValue>>();
while (reader.Read())
{
    // Work out calc
    List<PropertyValue> list;
    if (!result.TryGetValue(calc, out list))
    {
         list = new List<PropertyValue>();
         result[calc] = list;
    }
    list.Add(propValue);
}

Upvotes: 2

Zolt&#225;n Barna
Zolt&#225;n Barna

Reputation: 493

Is it possible to do something like this:

                lookUpForResult = result.ToLookup(x => x.Key.InnerID, x => x.Value);

                if (lookUpForResult.Contains(calc.InnerID))
                {
                    result.Add(calc, new List<PropertyValue> { propValue });
                }
                else
                {
                   (lookUpForResult[calc.InnerID]).Add(propValue);
                }

Upvotes: 0

schoetbi
schoetbi

Reputation: 12906

instead of

  tmpElementOfResult = result.Keys.FirstOrDefault(r => r.InnerID == calc.InnerID);

use

  result.ContainsKey(calc.InnerId);

to check if a key is present.

Upvotes: 1

Related Questions