2008-10-15 8 views
7

używam następującej składni pętli kolekcji listy:Jak uzyskać indeks obiektu w pętli For Each ... Next?

For Each PropertyActor As JCPropertyActor In MyProperty.PropertyActors 

    i = IndexOf(PropertyActor) 
Next 

Jak uzyskać indeks bieżącego obiektu w pętli? Używam IndexOf (PropertyActor), ale wydaje się to nieefektywne, ponieważ przeszukuje kolekcja, gdy już mam obiekt dostępny!

Odpowiedz

12

Indeks nie ma żadnego znaczenia do IEnumerable, czyli tego, czego używa konstrukcja foreach. Jest to ważne, ponieważ foreach może nie być wyliczane w kolejności indeksowania, jeśli twój konkretny typ kolekcji implementuje IEnumerable w dziwny sposób. Jeśli masz obiekt, który można uzyskać dostęp poprzez indeks i Ci zależy indeksu podczas iteracji, to jesteś lepiej po prostu przy użyciu tradycyjnych dla pętli:

for (int i=0;i<MyProperty.PropertyActors.Length;i++) 
{ 
    //... 
} 
2

tylko zainicjować zmienną całkowitą, przed wejściem do pętli i iteracyjne go ...

Dim i as Integer 
For Each PropertyActor As JCPropertyActor In MyProperty.PropertyActors 
    i++ 
Next 
+0

Zgodnie z domniemaniem Joela blok For Each używa interfejsu IEnumerable, który niekoniecznie używa tej samej kolejności co indeks. –

+0

Nadal uważam, że zmienna "i" da ci poprawną odpowiedź ... – sebagomez

1

Dodaj zmienną indeksu, który zwiększa się w każdej iteracji?

+0

tak, tak jak zrobiłem w kodzie, który podałem – sebagomez

12

AFAIK, ponieważ wyciąga obiekt z kolekcji, musisz wrócić do kolekcji, aby go znaleźć.

Jeśli potrzebujesz indeksu, zamiast używać go dla każdej pętli, po prostu użyłbym pętli for, która przeszła przez indeksy, więc wiesz, co masz.

+1

To podejście miałoby tę samą wadę, ponieważ kolekcje są hashlistami, a dostęp przez indeks jest tak złe, jak używanie indeksu. Użyj oddzielnego licznika, możesz sobie pozwolić na tę liczbę całkowitą. – tabdamage

+0

To może być, ale osobiście, jeśli potrzebujesz indeksu, pętla for ma dużo bardziej praktyczny sens i nie jest czymś, co będzie wyglądać nie na miejscu. –

6

to może być najłatwiej po prostu zachować oddzielny licznik:

i = 0 
For Each PropertyActor As JCPropertyActor In MyProperty.PropertyActors 
    ... 
    i = i + 1 
Next 

Tak na marginesie, Python posiada wygodny sposób robienia tego:

for i, x in enumerate(a): 
    print "object at index ", i, " is ", x 
+0

Nie rozumiem, dlaczego jest to tak różne od tego, co napisałem ... otrzymujesz +2, a otrzymałem -2 :( – sebagomez

+0

Utworzony/utrzymany indeks niekoniecznie będzie tym samym indeksem, który ma kolekcja (ponieważ foreach niekoniecznie jest to iteracja w kolejności indeksowej) Prawdopodobnie zostanie to również ocenione z innymi, podobnymi, błędnymi odpowiedziami –

+0

Bremen: Uznałbym to za zaskakujący wynik (a nie w dobry sposób). t faktycznie kodu w VB. –

1

Można użyć „FindIndex” metoda.

MyProperty.PropertyActors.FindIndex(Function(propActor As JCPropertyActor) propActor = JCPropertyActor) 

Ale wewnątrz pętli For Each, która wydaje się alot dodatkowego narzutu, i wydaje się tym samym problemem wynikającym jako „indexOf” metody. Sugeruję użycie staromodnej iteracji indeksu. W ten sposób masz swój indeks i swój przedmiot.

Dim PropertyActor As JCPropertyActor 
For i As Integer = 0 To MyProperty.PropertyActors.Count - 1 
    PropertyActor = MyProperty.PropertyActors.Item(i) 
Next