locked
How to: Detect last item in a List<> RRS feed

  • Question

  • User-1416423428 posted

    I need to know if I'm on the last item in my foreach loop.

    Here's my code. I need to apply class="last" for the last item in my loop. 

      if (result.Any())
      {
        <ul>
          @foreach (var latest in result)
          {
            
            <li><a href="/news?id=@latest.StoryID">@latest.StoryTitle</a></li>
          }
        </ul>
      }

    There is a .count() method that tells me how many items are in the list. I guess I could use a temp variable and increment that and compare if == to count(). 

    But is there a better way to detect if I'm currently on the last item in my loop?  Thanks. 

    Friday, June 13, 2014 6:19 PM

Answers

  • User-1416423428 posted

    Thanks for taking time to response. But for some reason, result is losing scope inside a for() loop. 

    I just did it this way.

    if (result.Any())
      {
        int i = 0;
        string lastClass = "";
        <ul>
          @foreach (var latest in result)
          {
            i++;
            lastClass = (i==result.Count()) ? "class=last" : "";
            <li @lastClass ><a href="/news?id=@latest.StoryID">@latest.StoryTitle</a></li>
          }
        </ul>
      }

    It works. 
     

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, June 13, 2014 7:09 PM

All replies

  • User-1423995609 posted

    What are you trying to do? If you want to render only latest news (the last item in your list), you could simply make a call on result and get the last item

    var lastItem = result.Last();

    However if you want to iterate thru list, and do something different on last item only, you can do

    if (result.Any())
      {
        <ul>
          
          @for(int i=0; i < result.Count;i++)
          {
            if(i == result.Count-1) // you're on the last item
            {
              <li>
                <a href="/news?id=@latest.StoryID">@latest.StoryTitle</a>
              </li>
            }
            else
            {
               // not the last item
            }
          }
        </ul>
      }

    Friday, June 13, 2014 6:46 PM
  • User-1416423428 posted

    Thanks for taking time to response. But for some reason, result is losing scope inside a for() loop. 

    I just did it this way.

    if (result.Any())
      {
        int i = 0;
        string lastClass = "";
        <ul>
          @foreach (var latest in result)
          {
            i++;
            lastClass = (i==result.Count()) ? "class=last" : "";
            <li @lastClass ><a href="/news?id=@latest.StoryID">@latest.StoryTitle</a></li>
          }
        </ul>
      }

    It works. 
     

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, June 13, 2014 7:09 PM
  • User-1423995609 posted

    Sorry, but I'm afraid I don't understand what do you mean by result is loosing scope inside a for() loop ?

    Also could you tell, what's the type of result? Is it IEnumerable<T>, or IList<T> ?

    Friday, June 13, 2014 7:24 PM
  • User895691971 posted

    You're right and wrong at the same time. The result isn't loosing the scope inside the loop. But instead it is always false. 

    You can see, that the first line of the code, 

    if (result.Any()) 
    {
      // code here...
    }

    Would only work if there is any element in the result List. If there is no element, it would skip and would result false. Since the condition would be only true, if the result List has any content, then the second block of your code would be false, 

    lastClass = (i==result.Count()) ? "class=last" : "";

    You've set the i to be 0. It would be only true if the Result List is null. But it isn't, that is why this block would be false and thus, the second value would be used to initialize the lastClass. 

    <li @lastClass><a href="/news?id=@latest.StoryID">@latest.StoryTitle</a></li>
    
    // would be
    
    <li ><a href="/news?id=1234>Love for All, Hatred for None!</a></li>

    This would be the result. I think you need to look twice at the logic you're trying to develop. 

    Saturday, June 14, 2014 3:53 AM
  • User-1416423428 posted

    You're right and wrong at the same time. The result isn't loosing the scope inside the loop. But instead it is always false. 

    You can see, that the first line of the code, 

    if (result.Any()) 
    {
      // code here...
    }

    My code works just fine.  If sql query returns empty, then I don't have to display anything. 

    If sql query returns some records, then I display all the resulting records... with the last record having an additional class called .last 

    Saturday, June 14, 2014 4:15 AM
  • User938738290 posted

    For the record, the reason Manvel's code didn't work is this:

    _Manvel_

    if(i == result.Count-1)

    Contrary to the title of the thread, result (Assuming it's directly returned from one of the Webmatrix.Data Database class methods) is not a List<dynamic>, but an IEnumerable<dynamic>.  IEnumerable requires you to use Count( ), the method, not Count, the property.

    So, nothing was "losing scope," people were just trying to call a property that doesn't exist.

    Afzaal, CASPartan's code comparing i to result.Count( ) directly, instead of subtracting 1, works because CASPartan increments i before doing the comparison.  Effectively, i runs from 1 to Count( ) instead of 0 to Count( ) - 1.  Trying to call result[i] (depending on where in the block you do it, yeah, yeah...) would skip the first element, and give you an IndexOutOfRangeException on the last iteration, but i is never used as an index, so it goes off without a hitch.

    Monday, June 23, 2014 9:12 AM