我有一个foreach循环,需要执行一些逻辑时,最后一项是从列表中选择,例如:
foreach (Item result in Model.Results)
{
//if current result is the last item in Model.Results
//then do something in the code
}
我可以知道哪个循环是最后没有使用循环和计数器吗?
我有一个foreach循环,需要执行一些逻辑时,最后一项是从列表中选择,例如:
foreach (Item result in Model.Results)
{
//if current result is the last item in Model.Results
//then do something in the code
}
我可以知道哪个循环是最后没有使用循环和计数器吗?
当前回答
接受的答案将不适用于集合中的副本。如果设置在foreach上,则可以添加自己的索引变量。
int last = Model.Results.Count - 1;
int index = 0;
foreach (Item result in Model.Results)
{
//Do Things
if (index == last)
//Do Things with the last result
index++;
}
其他回答
迭代器实现没有提供这一点。您的集合可能是一个IList,可以通过O(1)中的索引访问。在这种情况下,你可以使用一个普通的for循环:
for(int i = 0; i < Model.Results.Count; i++)
{
if(i == Model.Results.Count - 1) doMagic();
}
如果您知道计数,但不能通过索引访问(因此,result是一个ICollection),您可以通过在foreach的主体中增加i并将其与长度进行比较来进行计数。
所有这些都不是完美的优雅。克里斯的解决方案可能是我迄今为止见过的最好的。
接受的答案将不适用于集合中的副本。如果设置在foreach上,则可以添加自己的索引变量。
int last = Model.Results.Count - 1;
int index = 0;
foreach (Item result in Model.Results)
{
//Do Things
if (index == last)
//Do Things with the last result
index++;
}
你可以创建一个专门用于此的扩展方法:
public static class EnumerableExtensions {
public static bool IsLast<T>(this List<T> items, T item)
{
if (items.Count == 0)
return false;
T last = items[items.Count - 1];
return item.Equals(last);
}
}
你可以这样使用它:
foreach (Item result in Model.Results)
{
if(Model.Results.IsLast(result))
{
//do something in the code
}
}
还有更简单的方法吗?
Item last = null;
foreach (Item result in Model.Results)
{
// do something with each item
last = result;
}
//Here Item 'last' contains the last object that came in the last of foreach loop.
DoSomethingOnLastElement(last);
正如Shimmy所指出的,使用Last()可能会导致性能问题,例如,如果您的集合是LINQ表达式的实时结果。为了防止多次迭代,你可以使用“ForEach”扩展方法,如下所示:
var elements = new[] { "A", "B", "C" };
elements.ForEach((element, info) => {
if (!info.IsLast) {
Console.WriteLine(element);
} else {
Console.WriteLine("Last one: " + element);
}
});
扩展方法看起来像这样(作为额外的奖励,它还会告诉你索引,如果你在看第一个元素):
public static class EnumerableExtensions {
public delegate void ElementAction<in T>(T element, ElementInfo info);
public static void ForEach<T>(this IEnumerable<T> elements, ElementAction<T> action) {
using (IEnumerator<T> enumerator = elements.GetEnumerator())
{
bool isFirst = true;
bool hasNext = enumerator.MoveNext();
int index = 0;
while (hasNext)
{
T current = enumerator.Current;
hasNext = enumerator.MoveNext();
action(current, new ElementInfo(index, isFirst, !hasNext));
isFirst = false;
index++;
}
}
}
public struct ElementInfo {
public ElementInfo(int index, bool isFirst, bool isLast)
: this() {
Index = index;
IsFirst = isFirst;
IsLast = isLast;
}
public int Index { get; private set; }
public bool IsFirst { get; private set; }
public bool IsLast { get; private set; }
}
}