У меня есть foreach
цикл, и мне нужно выполнить некоторую логику, когда последний элемент выбран из List
, например:
foreach (Item result in Model.Results)
{
//if current result is the last item in Model.Results
//then do something in the code
}
Могу ли я узнать, какой цикл является последним без использования цикла и счетчиков?
Ответы:
Если вам просто нужно что-то сделать с последним элементом (в отличие от чего-то другого с последним элементом, то здесь поможет LINQ:
Если вам нужно сделать что-то другое с последним элементом, вам нужно что-то вроде:
Хотя вам, вероятно, нужно написать собственный компаратор, чтобы убедиться, что вы можете сказать, что элемент совпадает с элементом, возвращаемым
Last()
.Этот подход следует использовать с осторожностью, так как,
Last
возможно, придется повторять всю коллекцию. Хотя это не может быть проблемой для небольших коллекций, но если она станет большой, это может повлиять на производительность. Также произойдет сбой, если список содержит повторяющиеся элементы. В этом случае что-то вроде этого может быть более подходящим:источник
var last = Model.Result[Model.Result.Count - 1];
для более быстрого, чем использованиеLast()
Как насчет старой доброй петли?
Или используя Linq и foreach:
источник
Model.Results
естьIEnumerable
. Вы можете вызватьCount()
до цикла, но это может привести к полной итерации последовательности.Использование
Last()
определенных типов будет проходить через всю коллекцию!Это значит, что если вы делаете
foreach
колл и коллируетеLast()
, вы зациклились дважды! Я уверен, что вы хотели бы избежать в больших коллекциях.Тогда решение состоит в том, чтобы использовать
do while
цикл:Таким образом , если тип коллекции не имеет типа функция будет перебирать через все элементы коллекции.
IList<T>
Last()
Тест
Если ваша коллекция предоставляет произвольный доступ (например, орудия
IList<T>
), вы также можете проверить свой предмет следующим образом.источник
using
утверждение? Я думал, что это необходимо, только если объект обрабатывает ресурсы операционной системы, но не для управляемых структур данных.Как показывает Крис, Линк будет работать; просто используйте Last (), чтобы получить ссылку на последнюю в перечислимом, и, если вы не работаете с этой ссылкой, делайте обычный код, но если вы работаете с этой ссылкой, делайте свою дополнительную вещь. Недостатком является то, что это всегда будет O (N) -сложность.
Вместо этого вы можете использовать Count () (то есть O (1), если IEnumerable также является ICollection; это верно для большинства распространенных встроенных IEnumerables), и гибридизировать ваш foreach со счетчиком:
источник
источник
foreach
блокировкой. Как это:var lastItem = objList.LastOrDeafault();
. Затем с внутренней стороныforeach
петли вы можете проверить это следующим образом:f (item.Equals(lastItem)) { ... }
. В вашем исходном ответеobjList.LastOrDefault()
будет проходить итерацию по коллекции на каждой итерации "foreach" ( сложность полинома ).Как указал Шимми, использование Last () может быть проблемой производительности, например, если ваша коллекция является живым результатом выражения LINQ. Чтобы предотвратить несколько итераций, вы можете использовать метод расширения «ForEach», например:
Метод расширения выглядит следующим образом (в качестве дополнительного бонуса он также сообщит вам индекс и, если вы смотрите на первый элемент):
источник
Улучшив ответ Даниэля Вольфа, вы можете использовать другую,
IEnumerable
чтобы избежать нескольких итераций и лямбд, таких как:Реализация метода расширения:
источник
foreach
, что является улучшением.Реализация итератора не обеспечивает этого. Ваша коллекция может быть
IList
доступной через индекс в O (1). В этом случае вы можете использовать обычныйfor
-loop:Если вы знаете количество, но не можете получить доступ с помощью индексов (таким образом, результатом является
ICollection
), вы можете подсчитать себя, увеличив значениеi
вforeach
теле и сравнив его с длиной.Все это не совсем элегантно. Решение Криса может быть самым хорошим, которое я видел до сих пор.
источник
Как насчет немного более простого подхода.
источник
Лучшим подходом, вероятно, будет просто выполнить этот шаг после цикла: например,
Или если нужно что-то сделать до последнего результата
источник
Принятый ответ не будет работать для дубликатов в коллекции. Если вы настроены на
foreach
, вы можете просто добавить свои собственные индексные переменные.источник
используя Linq и foreach:
https://code.i-harness.com/en/q/7213ce
источник
«.Last ()» не работал для меня, поэтому я должен был сделать что-то вроде этого:
источник
Сделав небольшие изменения в превосходном коде Jon Skeet, вы даже можете сделать его умнее, предоставив доступ к предыдущему и следующему элементу. Конечно, это означает, что вам придется прочитать 1 пункт в реализации. По соображениям производительности предыдущий и следующий элемент сохраняются только для текущего элемента итерации. Это выглядит так:
источник
Как конвертировать,
foreach
чтобы отреагировать на последний элемент:источник
Просто сохраните предыдущее значение и работайте с ним внутри цикла. Тогда в конце «предыдущее» значение будет последним элементом, что позволит вам обрабатывать его по-другому. Нет подсчета или специальных библиотек не требуется.
источник
Вы можете просто использовать цикл for, и нет необходимости добавлять дополнительные
if
внутриfor
тела:Состояние
-1
infor
пропускает последний элемент.источник
Джон Скит недавно создал
SmartEnumerable<T>
тип, чтобы решить эту проблему. Вы можете увидеть его реализацию здесь:http://codeblog.jonskeet.uk/2007/07/27/smart-enumerations/
Для загрузки: http://www.yoda.arachsys.com/csharp/miscutil/
источник
Чтобы сделать что-то дополнительное для каждого элемента, кроме последнего, можно использовать подход на основе функций.
Этот подход имеет очевидные недостатки: меньшая ясность кода для более сложных случаев. Вызов делегатов может быть не очень эффективным. Устранение неполадок может быть не совсем простым. Яркая сторона - кодирование это весело!
Сказав это, я бы предложил использовать обычные циклы for в тривиальных случаях, если вы знаете, что счет вашей коллекции не очень медленный.
источник
Другой способ, который я не видел размещенным, состоит в том, чтобы использовать Очередь. Это аналог способа реализации метода SkipLast () без итерации больше, чем необходимо. Этот способ также позволит вам сделать это на любом количестве последних предметов.
Чтобы вызвать это, вы должны сделать следующее:
источник
источник
Вы можете сделать метод расширения, специально предназначенный для этого:
и вы можете использовать это так:
источник
Основываясь на ответе @ Shimmy, я создал метод расширения, который является решением, которое каждый хочет. Он прост, удобен в использовании и проходит через коллекцию только один раз.
Это работает на любом
IEnumerable<T>
. Использование выглядит так:Вывод выглядит так:
Кроме того, вы можете превратить это в
Select
метод стиля. Затем повторно используйте это расширение вForEach
. Этот код выглядит так:источник
Мы можем проверить последний элемент в цикле.
источник
источник
Вы можете сделать так:
источник