Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Removing Items in a List While Iterating Through It with For Each Loop

I have a list named NeededList I need to check each item in this list to see if it exists in my database. If it does exist in the database I need to remove it from the list. But I can't change the list while I'm iterating through it. How can I make this work?

Here is my code so far:

For Each Needed In NeededList
        Dim Ticker = Needed.Split("-")(0).Trim()
        Dim Year = Needed.Split("-")(1).Trim()
        Dim Period = Needed.Split("-")(2).Trim()
        Dim Table = Needed.Split("-")(3).Trim()
        Dim dr As OleDbDataReader
        Dim cmd2 As New OleDb.OleDbCommand("SELECT * FROM " & Table & " WHERE Ticker = ? AND [Year] = ? AND Period = ?", con)
        cmd2.Parameters.AddWithValue("?", Ticker)
        cmd2.Parameters.AddWithValue("?", Year)
        cmd2.Parameters.AddWithValue("?", Period)
        dr = cmd2.ExecuteReader
        If dr.HasRows Then
            NeededList.Remove(Needed)
        End If
Next
like image 945
gromit1 Avatar asked Oct 08 '13 15:10

gromit1


People also ask

How do you remove something from a list while iterating?

If you want to delete elements from a list while iterating, use a while-loop so you can alter the current index and end index after each deletion.

Can you remove elements in a for each loop?

The program needs access to the iterator in order to remove the current element. The for-each loop hides the iterator, so you cannot call remove .

Can we remove element from list while iterating Python?

We can delete multiple elements from a list while iterating, but we need to make sure that we are not invalidating the iterator. So either we need to create a copy of the list for iteration and then delete elements from the original list, or we can use the list comprehension or filter() function to do the same.

Can I modify list while iterating?

The general rule of thumb is that you don't modify a collection/array/list while iterating over it. Use a secondary list to store the items you want to act upon and execute that logic in a loop after your initial loop.


2 Answers

No you can't do that using a for each, but you can do that using the old fashioned for .. loop.
The trick is to start from the end and looping backwards.

For x = NeededList.Count - 1 to 0 Step -1
    ' Get the element to evaluate....
    Dim Needed = NeededList(x)
    .....
    If dr.HasRows Then
        NeededList.RemoveAt(x)
    End If
Next

You need to approach the loop in this way because you don't risk to skip elements because the current one has been deleted.

For example, suppose that you remove the fourth element in the collection, after that, the fifth element becomes the fourth. But then the indexer goes up to 5. In this way, the previous fifth element (now in fourth position) is never evaluated. Of course you could try to change the value of the indexer but this ends always in bad code and bugs waiting to happen.

like image 80
Steve Avatar answered Oct 05 '22 21:10

Steve


Go for safe and make a copy with ToList():

For Each Needed In NeededList.ToList()
    Dim Ticker = Needed.Split("-")(0).Trim()
    ...
    If dr.HasRows Then
        NeededList.Remove(Needed)
    End If
Next
like image 40
Henk Holterman Avatar answered Oct 05 '22 21:10

Henk Holterman