J'ai une liste nommée NeededList
Je dois vérifier chaque élément de cette liste pour voir s'il existe dans ma base de données. S'il existe dans la base de données, je dois le supprimer de la liste. Mais je ne peux pas changer la liste pendant que je parcours à travers elle. Comment puis-je faire ce travail?
Voici mon code jusqu'à présent:
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
Non, vous ne pouvez pas faire cela en utilisant un pour chacun, mais vous pouvez le faire en utilisant la boucle à l'ancienne.
L'astuce consiste à partir de la fin et à boucler en arrière.
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
Vous devez aborder la boucle de cette manière car vous ne risquez pas de sauter des éléments car celui en cours a été supprimé.
Par exemple, supposons que vous supprimiez le quatrième élément de la collection, puis que le cinquième devienne le quatrième. Mais alors l'indexeur monte à 5. De cette manière, le cinquième élément précédent (maintenant en quatrième position) n'est jamais évalué. Bien sûr, vous pouvez essayer de changer la valeur de l'indexeur mais cela finit toujours par un code incorrect et des bugs en attente.
Optez pour le coffre-fort et faites une copie avec ToList()
:
For Each Needed In NeededList.ToList()
Dim Ticker = Needed.Split("-")(0).Trim()
...
If dr.HasRows Then
NeededList.Remove(Needed)
End If
Next
Vous pouvez utiliser une boucle For pour parcourir chaque index à l’étape -1.
For i as Integer = NeededList.Count - 1 to 0 Step -1
Dim Needed = NeededList(i)
'this is a copy of your code
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
'MODIFIED CODE
If dr.HasRows Then NeededList.RemoveAt(i)
Next i
Le contenu d'un tableau (ou de tout ce que vous pouvez énumérer rapidement avec For Each
ne peut pas être modifié avec une boucle For Each
. Vous devez utiliser une simple boucle For
et parcourir tous les index.
Conseil: comme vous allez supprimer des index, je vous suggère de commencer par le dernier index et de vous diriger vers le premier index afin de ne pas en sauter un à chaque fois que vous en supprimez un.
Vous pouvez également inverser l'ordre des éléments de la liste et continuer à utiliser For Each
en utilisant les extensions IEnumerable Cast
et Reverse
.
Exemple simple utilisant une liste (de chaîne):
For Each Needed In NeededList.Cast(Of List(Of String)).Reverse()
If dr.HasRows Then
NeededList.Remove(Needed)
End If
Next
Que diriez-vous de cela (pas d'itération nécessaire):
NeededList = (NeededList.Where(Function(Needed) IsNeeded(Needed)).ToList
Function IsNeeded(Needed As ...) As Boolean
...
Return Not dr.HasRows
End Function
Non, vous ne pouvez pas supprimer d'une liste sur laquelle vous travaillez, par exemple . For Each Str As String dans listOfStrings Si Str.Equals ("Pat") Alors Dim index = listOfStrings.IndexOf (Str) listOfStrings .RemoveAt (index) Fin si Suivant
Mais cette méthode fonctionnera pour faire une copie de votre liste et la supprimer, par exemple . Pour chaque Str As String dans listOfStrings .__ Si Str.Equals ("Pat") Alors Dim index = listOfStringsCopy.IndexOf (Str) listOfStringsCopy.RemoveAt (index) Fin si Suivant