Reputation: 43
I have these two List<string>[]
the first one subj_cat1_id
contains a list of IDs and the second list AssignedSubjectsID
contains the IDs that are already assigned to the students. I need to loop into the first list subj_cat1_id
and remove from it all IDs that are equally found in the AssignedSubjectsID
list.
I'm using the following algorithm:
for (int i = 0; i != subject_cat1_id[0].Count; i++)
{
foreach (string id in AssignedSubjectsID[0])
{
if (subject_cat1_id[0][i] == id)
{
//add assigned subjects to student subject listbox
lst_sud_subjects.Items.Add(subject_cat1[0][i] + " (" + subjshort1 + ")");
ObjCache.SubjectAllocation.AssignedToID.Add(subject_cat1_id[0][i]);
//remove id and subj name from list
subject_cat1_id[0].RemoveAt(i);
subject_cat1[0].RemoveAt(i);
}
}
}
That's driving me since yesterday is that the outer For loop seems to be skipping IDs found in the List subject_cat1_id
.
Here's a test case:
subject_cat1_id contains IDs 1 to 22.
AssignedSubjectsID contains IDs 17,16,10,8,14 in that order.
The algorithm loops through 1-16, skips ID 17 and goes straight to ID 18.
My brain is not working anymore so any help would be well appreciated.
Thanks ~
Upvotes: 0
Views: 659
Reputation: 17382
subject_cat1_id[0].RemoveAt(i);
removes the element you are currently looking at with your outer loop's index i
. Thus all elements in that collection move one position towards the beginning of the list.
int i = 1;
['a', 'b', 'c', 'd', 'e'].RemoveAt(i)
results in
['a', 'c', 'd', 'e']
Thus for instance, the c
which was at index 2
before is now at index 1
. Before the next iteration of the loop starts, i
is incremented by 1. Continuing the previous example you now have
['a', 'c', 'd', 'e'].RemoveAt(2)
Which removes the d
and is, obviously, not what you want, because you skipped the c
.
Thus @FrankerZ's comment not to manipulate a list, while iterating it. Or if you must do, do it properly. Best practice is, to do it in reverse direction, because you already handled the later indexes.
for (int i = subject_cat1_id[0].Count-i; i >=0; i--) {
....
}
Upvotes: 2
Reputation: 5763
You can do that with Linq:
var remaining=subj_cat1_id[0].Except(AssignedSubjectsID[0]);
(I'm matching the posted code which only does this for the first item in each array.)
Upvotes: 1