web-dev-qa-db-fra.com

Est-il possible de faire un For ... Each Loop Backwards?

Je ne crois pas que cela soit possible par les méthodes conventionnelles, mais quelque chose comme ce code verbeux:

For Each s As String In myStringList Step -1
    //' Do stuff here
Next

Je devrai probablement inverser l'objet myString avant une boucle For..Each conventionnelle, correct?

33
Anders

Je pense que la documentation mentionnée dans la réponse est extrêmement trompeuse. L'ordre de For Each est défini par la collection qu'il a appelée (c'est-à-dire son implémentation de IEnumerableIEnumerable<T>), mais c'est non identique au fait de ne pas l'utiliser si l'ordre est important. Beaucoup de collections (telles que les tableaux, List<T>, etc.) vont toujours dans l'ordre "naturel".

Une partie de la documentation fait allusion à ceci:

_/Ordre de parcours. Lorsque vous exécutez un Pour chaque ... Prochaine boucle, traversée du fichier la collection est sous le contrôle du objet énumérateur retourné par le Méthode GetEnumerator. L'ordre de Le parcours n'est pas déterminé par Visual Basique, mais plutôt par le MoveNext méthode de l'objet énumérateur. Ce signifie que vous ne pourrez peut-être pas prédire quel élément de la la collection est la première à être retournée en élément, ou qui est le prochain à être retourné après un élément donné.

Ce n'est pas du tout la même chose que de dire qu'on ne peut pas s'y fier - on peut s'y fier si vous savez que la collection sur laquelle vous effectuez une itération produira les résultats dans l'ordre souhaité}. Ce n'est pas comme s'il allait sélectionner des éléments au hasard. Le comportement en termes de IEnumerable/IEnumerable<T> est clairement défini sur cette page.

Les exceptions les plus importantes aux ordres prévisibles sont les dictionnaires et les ensembles, qui sont naturellement non ordonnés.

Pour inverser un IEnumerable<T>, utilisez Enumerable.Reverse - mais si vous devez effectuer une itération inverse dans une collection indexée par position (telle qu'un tableau ou List<T>), il serait plus efficace d'utiliser une boucle For commençant par le fin et travail en arrière.

41
Jon Skeet

Vous devez faire quelque chose comme:

For i as integer = myStringList.Count-1 to 0 step -1
    dim s as string = myStringList.Item(i)
    ' Do your stuff with s
Next i

Mais pour autant que je sache, vous ne pouvez pas faire un "Pour ... Chacun" à l'envers, même si ce serait bien dans quelques cas.

36
SqlRyan

Malheureusement, le MSDN docs sur For Each indique que la construction For Each existe explicitement dans les cas où l'ordre de l'itération est sans importance (ensembles non ordonnés, etc.). Il n’existe donc malheureusement pas de concept pour inverser un For Each, car l’ordre n’est pas défini.

Bonne chance!

13
Mike

Appelez la méthode System.Linq.Enumerable.Reverse pour obtenir une IEnuemrable(Of TSource) dans l'ordre inverse de votre source énumérable.

10
Amy B
For Each s As String In myStringList.Reverse
    //' Do stuff here
Next
3
Tonko Boekhoud

Test dans Framework 4, le code 

For Each s As String In myStringList.Reverse
    //' Do stuff here
Next

cela ne fonctionnait pas, la bonne façon de le faire est: 

myStringList.Reverse() ' it is a method not a function
For Each s As String In myStringList
//' Do stuff here
Next

Regardez: MSDN: Reserve

3
Dave

La raison pour laquelle cela est impossible est que, en tant que fonctionnalité de conception de base, For Each peut effectuer une itération sur un objet énumérable sans dernier élément, ou avec un dernier élément encore inconnu.

1
reinierpost

Ce que vous devez faire est de créer un tableau avec votre pour chacun de ceux que vous aviez auparavant, puis utilisez array.reverse et exécutez le pour chacun sur le tableau. Terminé

À votre santé

0
xxxmandoxxx

En fonction de ce qui se passe dans votre boucle, vous pouvez faire un .InsertAt (objet, 0) au lieu d'un .Add et produire le même résultat qu'une énumération inverse.

0
Michael J. Berry

vous devez d’abord créer une liste (de chaîne) pour chaque instruction, puis créer une autre action normale pour .. étape -1 ..instruction. voir un exemple:

Dim ff As New List(Of Integer)
For Each rRow As DataRow In DeletedRows
Dim item As Integer
item = rRow.Table.Rows.IndexOf(rRow)
ff.Add(item)
Next
For i As Integer = ff.Count - 1 To 0 Step -1
dim item as integer=ff(i)
next i

j'espère que ça vous sera utile

0
Hisham Shaaban

'créez une liste de tout ce que vous voulez et parcourez For Loop Collecting

dim revList as New List (of ToolStripItem)  
For each objItem as ToolStripItem in Menu.DropDownItems
    revList.Add(objItem)
next
revList.reverse ' reverse the order of that list

'parcourir la liste ordonnée en ordre inverse 

for each objItem as ToolStripItem in revList   
    ' do whatever (like removing your menu from an ArrayMenu)
next

'remplace ToolStripItem et Menu.DropDownItems par tout ce dont vous avez besoin

0
Georg

La réponse acceptée explique pourquoi, mais pour ajouter un autre exemple, vous pouvez faire pour une collection avec clé (SortedList, SortedDictionary, Dictionary, etc.)

For Each Id as Tkey in MyCollection.Keys.Reverse
   // The item in question is now available as MyCollection(Id)
Next
0
Adam

Vous pouvez ajouter une fonction étendue à la classe que vous essayez d'inverser. 

<Serializable()> Public Class SomeCollection
    Inherits CollectionBase
    Public Sub New()
    End Sub

    Public Sub Add(ByVal Value As Something)
        Me.List.Add(Value)
    End Sub

    Public Sub Remove(ByVal Value As Something)
        Me.List.Remove(Value)
    End Sub

    Public Function Contains(ByVal Value As Something) As Boolean
        Return Me.List.Contains(Value)
    End Function

    Public Function Item(ByVal Index As Integer) As Something
        Return DirectCast(Me.List.Item(Index), Something)
    End Function

    Public Function Reverse() As SomeCollection
        Dim revList As SomeCollection = New SomeCollection()
        For index As Integer = (Me.List.Count - 1) To 0 Step -1
             revList.List.Add(Me.List.Item(index))
        Next
        Return revList
    End Function
End Class

Alors tu l'appellerais comme ça

For Each s As Something In SomeCollection.Reverse

Next
0
DotNet Programmer