Subject
I have to iterate through a collection of objects (in this case IGrouping<string, SupplyDemand>
). So I could do this easyly using a query with LINQ.
Code
public IEnumerable<string> getParentPegs(IGrouping<string, SupplyDemand> data)
{
IEnumerable<string> query =
from d in data
where d.Source.ToLower() == "make"
select d.Part;
return query;
}
Problem
I'm using this function inside a loop in a VSTO Excel project and it's pretty slow, besides it stops running (memory leak). So I came up with the following code:
Improved Code
public List<string> getParentPegs(IGrouping<string, SupplyDemand> data)
{
List<string> result = new List<string>();
var enumerator = data.GetEnumerator();
while (enumerator.MoveNext())
{
SupplyDemand obj = enumerator.Current;
if (obj.Source.ToLower() == "make")
{
result.Add(obj.Peg);
}
}
return result;
}
Question
Is there any other way to improve this?
2 Answers 2
You can do the same with just a foreach
loop instead of reading the enumerator.
You can use the String.Compare
method to do a case insensetive compare instead of creating a lowercase version of each string that you compare.
Improved improved code:
public List<string> getParentPegs(IGrouping<string, SupplyDemand> data) {
List<string> result = new List<string>();
foreach (SupplyDemand obj in data) {
if (String.Compare(obj.Source, "make", true) == 0) {
result.Add(obj.Peg);
}
}
return result;
}
Note: In your first code you are getting the property Part
, but in the second you are getting the property Peg
instead.
how about this :
public IEnumerable<string> GetParentPegs(IGrouping<string, SupplyDemand> data)
{
foreach(var d in data)
if(d.Source.ToLower() == "make") yield return d.Part;
}
-
\$\begingroup\$ Excellent!, But how come that this is faster than my second example? \$\endgroup\$Eder– Eder2012年02月25日 22:43:08 +00:00Commented Feb 25, 2012 at 22:43
-
\$\begingroup\$ It actually does the same thing but it's a bit more readable in my opinion \$\endgroup\$Beatles1692– Beatles16922012年02月25日 23:02:48 +00:00Commented Feb 25, 2012 at 23:02
-
1\$\begingroup\$ It might be faster if you are not evaluating the result of
GetParentPegs
immediately, since the loop inGetParentPegs
will only be executed when theIEnumerable<string>
is enumerated. \$\endgroup\$Olivier Jacot-Descombes– Olivier Jacot-Descombes2012年02月26日 00:18:43 +00:00Commented Feb 26, 2012 at 0:18
var pegs = getParentPegs(....); int count = pegs.Count(); foreach(var peg in pegs){ // Doing something else here }
Will cause your expression to be evaluated twice, whereas the improved code will only evaluate it once. You can overcome this by forcing it to evaluate and store it in a list by calling the .ToList() method: var pegs = getParentPegs(...).ToList(); Or return a List within getParentPegs. \$\endgroup\$