简体   繁体   中英

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 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 ~

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--) {
    ....
}

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.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM