Reputation: 2864
I have List of (PatchFacilityManager) and a List of (Int) facilityManagerId. I want to make the below code efficient. Is there any way to remove these two foreach loop.
foreach (PatchFacilityManager PM in patchFacilityManager)
{
foreach (int FM in facilityManagerId)
{
if (PM.FacilityManagerId == FM)
{
PM.IsSelected = true;
}
}
}
Upvotes: 4
Views: 454
Reputation: 43217
Here's one way,
foreach (PatchFacilityManager PM in patchFacilityManager)
{
PM.IsSelected = facilityManagerId.Contains(PM.FacilityManagerId);
}
This solution is efficient in two three ways IMHO as compared to the code given in the question.
First, it does not test for the condition and the result of the expression is straight away assigned into PM.IsSelected. As per LukeH's comment, it is mandatory to not set the PM.IsSelected to false, so the condition is unavoidable. However this improvement is applicable if the asked needs to set it to false. . From question asker's comment, his case seem to go right with this optimization. So no need for conditional assignment.
Second, it does not iterate through whole list, since List.Contains(int), returns true and come out of loop on the first occurrence of the int passed in argument.
Third, when framework gives you the functionality List.Contains(int), then why re-invent the wheel. So from maintenance perspective this is also more efficient.
Upvotes: 7
Reputation: 64557
Just for fun and outside the box - an approach when the lists are sorted:
static void Main(string[] args)
{
List<int> nums = new List<int>(new int[] { 1, 2, 3, 4, 5, 6, 7, 8 });
List<int> ids = new List<int>(new int[] { 2, 4, 5 });
for (int i = 0, j = 0; i < nums.Count && j < ids.Count; i++)
{
int num = nums[i];
int id = ids[j];
if (num == id)
{
Console.WriteLine("Match = " + id);
j++;
}
}
Console.ReadLine();
}
I presume no knowledge of the performance benefit or detrement of this idea. Of course you can modify this to use a main foreach for the numbers and you manually use the Enumerator of the IDs inside the main foreach if you have allergies to fors.
Upvotes: 0
Reputation: 8008
Another variant using LINQ syntax:
var match = for PM in patchFacilityManager
join FM in facilityManager on PM.FacilityManagerId equals FM
select PM;
foreach(var PM in match)
{
PM.IsSelected = true;
}
Upvotes: 0
Reputation: 7458
patchFacilityManager
.Where(c => facilityManagerId.Contains(c.FacilityManagerId))
.ForEach(c => c.IsSelected = true);
Upvotes: 1
Reputation: 40559
patchFacilityManager
.Where(m => facilityManagerId.Contains(m.FacilityManagerId))
.ToList()
.ForEach(m => m.IsSelected = true);
or
patchFacilityManager
.Join(facilityManagerId, m => m.FacilityManagerId, f => f, (m,f) => m)
.ToList()
.ForEach(m => m.IsSelected = true);
Upvotes: 0
Reputation: 269658
var ids = new HashSet<int>(facilityManagerId);
foreach (PatchFacilityManager pfm in patchFacilityManager)
{
if (ids.Contains(pfm.FacilityManagerId))
pfm.IsSelected = true;
}
Upvotes: 1
Reputation: 457472
You could store the facility manager id's in an array in sorted order, and then look them up using BinarySearch
instead of a foreach
.
Upvotes: 0