mis*_*hap 216 c# asp.net foreach
我有一个foreach循环,需要在从中选择最后一项时执行一些逻辑List,例如:
foreach (Item result in Model.Results)
{
//if current result is the last item in Model.Results
//then do something in the code
}
Run Code Online (Sandbox Code Playgroud)
如果不使用for循环和计数器,我可以知道哪个循环是最后的吗?
Chr*_*isF 264
如果你只需要对最后一个元素做一些事情(而不是与最后一个元素不同的东西,那么使用LINQ将有助于:
Item last = Model.Results.Last();
// do something with last
Run Code Online (Sandbox Code Playgroud)
如果您需要对最后一个元素做一些不同的事情,那么您需要以下内容:
Item last = Model.Results.Last();
foreach (Item result in Model.Results)
{
// do something with each item
if (result.Equals(last))
{
// do something different with the last item
}
else
{
// do something different with every item but the last
}
}
Run Code Online (Sandbox Code Playgroud)
虽然您可能需要编写自定义比较器,以确保您可以告诉该项目与返回的项目相同Last().
应谨慎使用此方法,因为Last可能必须遍历集合.虽然这对于小型集合来说可能不是问题,但如果它变大,它可能会对性能产生影响.如果列表包含重复项,它也将失败.在这种情况下,这样的事情可能更合适:
int totalCount = result.Count();
for (int count = 0; count < totalCount; count++)
{
Item result = Model.Results[count];
count++;
// do something with each item
if (count == totalCount)
{
// do something different with the last item
}
else
{
// do something different with every item but the last
}
}
Run Code Online (Sandbox Code Playgroud)
Fio*_*ite 168
一个好的老式循环怎么样?
for (int i = 0; i < Model.Results.Count; i++) {
if (i == Model.Results.Count - 1) {
// this is the last item
}
}
Run Code Online (Sandbox Code Playgroud)
或者使用Linq和foreach:
foreach (Item result in Model.Results)
{
if (Model.Results.IndexOf(result) == Model.Results.Count - 1) {
// this is the last item
}
}
Run Code Online (Sandbox Code Playgroud)
Kei*_*thS 37
正如克里斯所说,Linq将会工作; 只需使用Last()来获取对枚举中最后一个的引用,并且只要您不使用该引用然后执行正常的代码,但是如果您正在使用该引用,那么请执行额外的操作.它的缺点是它总是O(N) - 复杂性.
您可以使用Count()(如果IEnumerable也是ICollection,则为O(1);对于大多数常见的内置IEnumebles,这是正确的),并将foreach与计数器混合:
var i=0;
var count = Model.Results.Count();
foreach (Item result in Model.Results)
{
if(++i==count) //this is the last item
}
Run Code Online (Sandbox Code Playgroud)
Shi*_*mmy 37
Last()在某些类型上使用将循环通过整个集合!
意思是如果你foreach打电话Last(),你就打了两次!我敢肯定你想在大集合中避免.
然后解决方案是使用do while循环:
using (var enumerator = collection.GetEnumerator())
{
var last = !enumerator.MoveNext();
T current;
while(!last)
{
current = enumerator.Current;
//process item
last = !enumerator.MoveNext();
//process item extension according to flag; flag means item
}
}
Run Code Online (Sandbox Code Playgroud)
除非集合类型是类型IList<T>,否则Last()函数将遍历所有集合元素.
小智 19
foreach (var item in objList)
{
if(objList.LastOrDefault().Equals(item))
{
}
}
Run Code Online (Sandbox Code Playgroud)
Dan*_*olf 10
正如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);
}
});
Run Code Online (Sandbox Code Playgroud)
扩展方法看起来像这样(作为一个额外的奖励,它还会告诉你索引,如果你正在查看第一个元素):
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; }
}
}
Run Code Online (Sandbox Code Playgroud)
迭代器实现没有提供.您的集合可能IList是可通过O(1)中的索引访问的集合.在这种情况下,您可以使用正常的for循环:
for(int i = 0; i < Model.Results.Count; i++)
{
if(i == Model.Results.Count - 1) doMagic();
}
Run Code Online (Sandbox Code Playgroud)
如果你知道计数,而是通过指标(因此,结果是不能访问ICollection),你可以通过增加一个计数自己i的foreach的身体,它比较长.
这一切都不是很优雅.克里斯的解决方案可能是迄今为止我见过的最好的解决方案.
最好的方法可能只是在循环后执行该步骤:例如
foreach(Item result in Model.Results)
{
//loop logic
}
//Post execution logic
Run Code Online (Sandbox Code Playgroud)
或者如果你需要对最后的结果做些什么
foreach(Item result in Model.Results)
{
//loop logic
}
Item lastItem = Model.Results[Model.Results.Count - 1];
//Execute logic on lastItem here
Run Code Online (Sandbox Code Playgroud)
小智 5
怎么样简单的方法.
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);
Run Code Online (Sandbox Code Playgroud)
进一步提高Daniel Wolf的答案,您可以将其堆叠在一起,IEnumerable以避免多次迭代和lambda,例如:
var elements = new[] { "A", "B", "C" };
foreach (var e in elements.Detailed())
{
if (!e.IsLast) {
Console.WriteLine(e.Value);
} else {
Console.WriteLine("Last one: " + e.Value);
}
}
Run Code Online (Sandbox Code Playgroud)
扩展方法的实现:
public static class EnumerableExtensions {
public static IEnumerable<IterationElement<T>> Detailed<T>(this IEnumerable<T> source)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
using (var enumerator = source.GetEnumerator())
{
bool isFirst = true;
bool hasNext = enumerator.MoveNext();
int index = 0;
while (hasNext)
{
T current = enumerator.Current;
hasNext = enumerator.MoveNext();
yield return new IterationElement<T>(index, current, isFirst, !hasNext);
isFirst = false;
index++;
}
}
}
public struct IterationElement<T>
{
public int Index { get; }
public bool IsFirst { get; }
public bool IsLast { get; }
public T Value { get; }
public IterationElement(int index, T value, bool isFirst, bool isLast)
{
Index = index;
IsFirst = isFirst;
IsLast = isLast;
Value = value;
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
214504 次 |
| 最近记录: |