cedroid09
cedroid09

Reputation: 43

C# List sorting with For Loop

I have these two List<string>[] the first one subj_cat1_id contains a list of IDs and the second list AssignedSubjectsIDcontains 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

Answers (2)

derpirscher
derpirscher

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

Richardissimo
Richardissimo

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

Related Questions