8

I have this code :

foreach (Object element in elements.under)
{
    ...
}

and I'd like to print some only when I'm into the last cycle. How can I do it?

KyleMit
  • 30,350
  • 66
  • 462
  • 664
markzzz
  • 47,390
  • 120
  • 299
  • 507

5 Answers5

9

You can try this:

foreach (Object element in elements.under)
{
    if (element  == elements.under.Last())  
    {
        //Print Code
    }
    else
    {
        //Do other thing here
    }
}
KyleMit
  • 30,350
  • 66
  • 462
  • 664
Rio Stephen
  • 245
  • 1
  • 3
  • 8
  • 1
    This is bad code that can yield bad performance. If `under` does not support random access (i.e. implement the [`IList<>` interface](https://learn.microsoft.com/dotnet/api/system.collections.generic.ilist-1), like an array and `List<>` do) then `Last()` will have to enumerate _every_ element of `under` for _every_ iteration of the `foreach`. – Lance U. Matthews Nov 10 '21 at 04:49
8

You need to keep track of a counter and then check for last element -

int i = 1;
foreach (Object element in elements.under)
{
    if (i == elements.under.Count) //Use count or length as supported by your collection
    { 
      //last element 
    }
    else 
    { i++; }
}
Sachin Shanbhag
  • 54,530
  • 11
  • 89
  • 103
3

Adapted from this post on Enumerating with extra info in the Miscellaneous Utility Library

foreach (SmartEnumerable<string>.Entry entry in new SmartEnumerable<string>(list))
{
    Console.WriteLine ("{0,-7} {1} ({2}) {3}",
                        entry.IsLast  ? "Last ->" : "",
                        entry.Value,
                        entry.Index,
                        entry.IsFirst ? "<- First" : "");
}

See Also: How do you find the last loop in a For Each (VB.NET)?

KyleMit
  • 30,350
  • 66
  • 462
  • 664
Pranay Rana
  • 175,020
  • 35
  • 237
  • 263
0

You can try this simple code

foreach (object obj in allObjects)
{ 
    if (obj  != allObjects.Last())
    {
            // Do some cool stufff..
    } else
    {
            // Go Normal Way
    }
}
KyleMit
  • 30,350
  • 66
  • 462
  • 664
Sayed Muhammad Idrees
  • 1,245
  • 15
  • 25
  • This is the same as [Rio Stephen's answer](https://stackoverflow.com/a/38449313/150605) and bad for the same reason: if `allObjects` does not support random access (i.e. implement the [`IList<>` interface](https://learn.microsoft.com/dotnet/api/system.collections.generic.ilist-1), like an array and `List<>` do) then `Last()` will have to enumerate _every_ element of `allObjects` for _every_ iteration of the `foreach`. – Lance U. Matthews Nov 10 '21 at 04:52
  • @LanceU.Matthews Well this is the only way with getting `list.last();` – Sayed Muhammad Idrees Nov 17 '21 at 08:51
0

Extensible Solution

Borrowing from python's enumerate function, you can wrap a collection and return a tuple of values, containing the actual item along with any extra helpful data

Here's a simple extension method that returns the item, it's index, and if it's the first / last item.

public static class ListExtensions
{
    public static IEnumerable<(T element, int index, bool isFirst, bool isLast)> Enumerate<T>(this IEnumerable<T> list) {
        var len = list.Count();     
        return list.Select((el, i) => (el, i, i == 0, i == len - 1));
    }
}

Then you can use it like this:

var list = new[] {'A','B','C'};
foreach(var (el, i, isFirst, isLast) in list.Enumerate()) {
    Console.WriteLine($"el={el}, i={i}, isFirst={isFirst}, isLast={isLast}");
}

// el=A, i=0, isFirst=True,  isLast=False
// el=B, i=1, isFirst=False, isLast=False
// el=C, i=2, isFirst=False, isLast=True

Optimized Solution

The previous solution technically loops over the list twice (to get the length and return each item). For a minor performance improvement, you can check for the last item by looping over the enumerator like this:

public static class ListExtensions
{
    public static IEnumerable<(T element, bool isFirst, bool isLast)> Enumerate<T>(this IEnumerable<T> collection) {
        using var enumerator = collection.GetEnumerator();
        var isFirst = true;
        var isLast = !enumerator.MoveNext();

        while (!isLast)
        {
            var current = enumerator.Current;        
            isLast = !enumerator.MoveNext();

            yield return (current, isFirst, isLast);
            
            isFirst = false;
        }
    }
}

And then use like this:

var list = new[] {'A','B','C'};
foreach(var (el, isFirst, isLast) in list.Enumerate()) {
    Console.WriteLine($"el={el}, isFirst={isFirst}, isLast={isLast}");
}

// el=A, isFirst=True,  isLast=False
// el=B, isFirst=False, isLast=False
// el=C, isFirst=False, isLast=True

Demo in DotNet Fiddle

Further Reading

KyleMit
  • 30,350
  • 66
  • 462
  • 664