Mam foreach
pętlę i muszę wykonać pewną logikę, gdy ostatni element jest wybrany z List
, np .:
foreach (Item result in Model.Results)
{
//if current result is the last item in Model.Results
//then do something in the code
}
Czy mogę wiedzieć, która pętla jest ostatnia bez użycia pętli i liczników?
Odpowiedzi:
Jeśli potrzebujesz zrobić coś z ostatnim elementem (w przeciwieństwie do czegoś innego z ostatnim elementem, skorzystanie z LINQ pomoże tutaj:
Jeśli chcesz zrobić coś innego z ostatnim elementem, potrzebujesz czegoś takiego:
Chociaż prawdopodobnie będziesz musiał napisać niestandardowy moduł porównujący, aby upewnić się, że możesz powiedzieć, że element był taki sam, jak element zwracany przez
Last()
.Takie podejście należy stosować ostrożnie, ponieważ
Last
może być konieczne powtarzanie kolekcji. Chociaż może to nie stanowić problemu w przypadku małych kolekcji, jeśli się powiększy, może to mieć wpływ na wydajność. Nie powiedzie się również, jeśli lista zawiera zduplikowane elementy. W takich przypadkach coś takiego może być bardziej odpowiednie:źródło
var last = Model.Result[Model.Result.Count - 1];
szybciej niż za pomocąLast()
Co powiesz na dobrą, staroświecką pętlę?
Lub używając Linq i foreach:
źródło
Model.Results
jestIEnumerable
. Możesz wywoływaćCount()
przed pętlą, ale może to spowodować pełną iterację sekwencji.Używanie
Last()
na niektórych typach zapętli całą kolekcję!Oznacza to, że jeśli wykonasz a
foreach
i zadzwoniszLast()
, zapętlisz dwa razy!czego jestem pewien, że chciałbyś uniknąć w dużych kolekcjach.Następnie rozwiązaniem jest użycie
do while
pętli:Więc chyba rodzaj kolekcja jest typu funkcja iteracyjne thru wszystkich elementów kolekcji.
IList<T>
Last()
Test
Jeśli Twoja kolekcja zapewnia dostęp losowy (np. Narzędzia
IList<T>
), możesz również sprawdzić swój przedmiot w następujący sposób.źródło
using
instrukcji? Pomyślałem, że jest to potrzebne tylko wtedy, gdy obiekt obsługuje zasoby systemu operacyjnego, ale nie w przypadku zarządzanych struktur danych.Jak pokazuje Chris, Linq będzie działać; po prostu użyj Last (), aby uzyskać odwołanie do ostatniego w wyliczalnym, i dopóki nie pracujesz z tym odwołaniem, zrób normalny kod, ale jeśli pracujesz z tym odwołaniem, zrób dodatkową rzecz. Jego wadą jest to, że zawsze będzie to złożoność O (N).
Zamiast tego możesz użyć funkcji Count () (która jest O (1), jeśli IEnumerable jest również ICollection; jest to prawdą w przypadku większości typowych wbudowanych IEnumerables), i możesz połączyć swój foreach z licznikiem:
źródło
źródło
foreach
blokiem. Tak:var lastItem = objList.LastOrDeafault();
. Następnie od wewnątrzforeach
pętli można to sprawdzić w następujący sposób:f (item.Equals(lastItem)) { ... }
. W twojej oryginalnej odpowiedziobjList.LastOrDefault()
iterowałaby kolekcja po każdej iteracji „foreach” ( dotyczy to złożoności wielomianowej ).Jak wskazał Shimmy, użycie Last () może stanowić problem z wydajnością, na przykład, jeśli twoja kolekcja jest żywym wynikiem wyrażenia LINQ. Aby zapobiec wielokrotnym iteracjom, możesz użyć metody rozszerzenia „ForEach” w następujący sposób:
Metoda rozszerzenia wygląda następująco (jako dodatkowy bonus, powie ci również indeks i jeśli patrzysz na pierwszy element):
źródło
Ulepszając odpowiedź Daniela Wolfa, możesz jeszcze postawić na innym,
IEnumerable
aby uniknąć wielu iteracji i lambd, takich jak:Implementacja metody rozszerzenia:
źródło
foreach
, co jest ulepszeniem.Implementacja iteratora tego nie zapewnia. Twoja kolekcja może być
IList
dostępna za pośrednictwem indeksu w O (1). W takim przypadku możesz użyć normalnejfor
pętli:Jeśli znasz liczbę, ale nie możesz uzyskać dostępu za pomocą indeksów (dlatego wynikiem jest an
ICollection
), możesz policzyć siebie, zwiększając wartośći
wforeach
ciele i porównując ją z długością.Wszystko to nie jest idealnie eleganckie. Rozwiązanie Chrisa może być najładniejsze, jakie do tej pory widziałem.
źródło
Co powiesz na trochę prostsze podejście.
źródło
Najlepszym rozwiązaniem byłoby prawdopodobnie wykonanie tego kroku po pętli: np
Lub jeśli musisz zrobić coś z ostatnim rezultatem
źródło
Akceptowana odpowiedź nie będzie działać dla duplikatów w kolekcji. Jeśli ustawiono opcję
foreach
, możesz po prostu dodać własne zmienne indeksujące.źródło
używając Linq i foreach:
https://code.i-harness.com/en/q/7213ce
źródło
„.Last ()” nie działało dla mnie, więc musiałem zrobić coś takiego:
źródło
Wprowadzając drobne poprawki w doskonałym kodzie Jona Skeeta, możesz nawet uczynić go bardziej inteligentnym, umożliwiając dostęp do poprzedniego i następnego elementu. Oczywiście oznacza to, że będziesz musiał przeczytać z wyprzedzeniem 1 element w implementacji. Ze względu na wydajność poprzedni i następny element są zachowywane tylko dla bieżącego elementu iteracji. To wygląda tak:
źródło
Jak przekonwertować,
foreach
aby zareagować na ostatni element:źródło
Wystarczy zapisać poprzednią wartość i pracować z nią w pętli. Następnie na końcu „poprzednia” wartość będzie ostatnim elementem, co pozwoli ci postępować inaczej. Nie wymaga liczenia ani specjalnych bibliotek.
źródło
Możesz po prostu użyć pętli for i nie ma potrzeby dodawania dodatkowych elementów
if
wewnątrzfor
ciała:-1
Wfor
stanie dba o pomijam ostatni element.źródło
Jon Skeet stworzył kiedyś jakiś
SmartEnumerable<T>
typ rozwiązania tego konkretnego problemu. Możesz zobaczyć jego implementację tutaj:http://codeblog.jonskeet.uk/2007/07/27/smart-enumerations/
Aby pobrać: http://www.yoda.arachsys.com/csharp/miscutil/
źródło
Aby zrobić coś dodatkowego dla każdego elementu oprócz ostatniego, można zastosować podejście oparte na funkcjach.
Podejście to ma oczywiste wady: mniej klarowności kodu w bardziej złożonych przypadkach. Dzwonienie do delegatów może nie być bardzo skuteczne. Rozwiązywanie problemów może nie być łatwe. Jasna strona - kodowanie jest fajne!
Powiedziawszy to, sugerowałbym użycie zwykłego dla pętli w trywialnych przypadkach, jeśli wiesz, że liczba twoich kolekcji nie jest strasznie wolna.
źródło
Innym sposobem, którego nie widziałem, jest użycie kolejki. Jest to analogiczne do sposobu implementacji metody SkipLast () bez iteracji więcej niż to konieczne. W ten sposób możesz to zrobić na dowolnej liczbie ostatnich elementów.
Aby to nazwać, wykonaj następujące czynności:
źródło
źródło
Możesz utworzyć metodę rozszerzenia specjalnie dedykowaną do tego:
i możesz użyć tego w następujący sposób:
źródło
Na podstawie odpowiedzi @ Shimmy stworzyłem metodę rozszerzenia, która jest rozwiązaniem, którego wszyscy chcą. Jest prosty, łatwy w użyciu i tylko raz zapętla kolekcję.
Działa to na każdym
IEnumerable<T>
. Sposób użycia wygląda następująco:Wyjście wygląda następująco:
Dodatkowo możesz zrobić z tego
Select
metodę stylu. Następnie ponownie użyj tego rozszerzenia wForEach
. Ten kod wygląda następująco:źródło
Możemy sprawdzić ostatni element w pętli.
źródło
źródło
Możesz to zrobić w następujący sposób:
źródło