tags:

views:

570

answers:

10
foreach (Item i in Items)

 {
      do something with i;
      do another thing with i (but not if last item in collection);
 }
+23  A: 

Better to use a for loop:

int itemCount = Items.Count;
for (int i = 0; i < itemCount; i++)
{
    var item = Items[i];

    // do something with item

    if (i != itemCount - 1)
    {
        // do another thing with item
    } 
}
Ben M
+1 though this only works if the Items collection is indexed.
Jon Seigel
+1, beat me to the punch.
John M Gant
...of course the notion of the last item in a collection is meaningless if the collection isn't indexed.
Jon Seigel
@Jon: Not at all. An `IEnumerable<T>` is inherently ordered but not indexed.
Jon Skeet
(Or perhaps more accurately, it's inherently ordered, but doesn't have random access by index, nor does it provide a count up front.)
Jon Skeet
@Jon: Good point. I learned something today. Thanks.
Jon Seigel
thanks for answer, but have to give it to jon skeet because his solution still uses foreach which worked out.
zsharp
+2  A: 

How about a for loop instead of a foreach.

for (int i = 0; i < Items.Count; i++) {
    //do something with i;
    if (i == Items.Count - 1) {
        //do another thing with Items[Items.count - 1];
    }
}
John M Gant
+8  A: 

I have a helper class for this in MiscUtil. Sample code (from the first link):

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" : "");
}

This is simpler if you're using .NET 3.5 and C# 3 so you can use extension methods and implicit typing:

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

The nice thing about this over using a for loop is that it works with IEnumerable<T> instead of IList<T> so you can use it with LINQ etc without buffering everything. (It maintains a single-entry buffer internally, mind you.)

Jon Skeet
That's nice. Have looked at your MiscUtil library before but got a bit overwhelmed with all that was there. I'm sure there are loads of nice things like this. If only I had time to go and look. :)
Matt Lacey
"usually in order to output some sort of separator between items or something similar" - exactly my issue
zsharp
It's a bit of a grab-bag, yes. At some point I should either separate it out or at least move it onto code.google.com. It's just a case of finding the time... On the plus side, the way I've implemented it you can *usually* just grab a class or two instead of taking the whole library.
Jon Skeet
@zsharp, you really should have mentioned what you were trying to do: you can use string.Join() for this!
tster
+4  A: 
foreach (Item i in Items.Take(Items.Count - 1))
{
      do something with i;
      do another thing with i (but not if last item in collection);
}
Kamarey
This doesn't work, since it doesn't perform the first operation with the last item.
Ben M
Yep, the first operation should be repeated after the loop for the last item.
Kamarey
A: 

Supposing you are using C# 3.0.

using System.Linq;

foreach (item i in c)
{
    if (i == c.Last())
       return;

    // do something with i;
}
Marwan Aouida
The complexity of the Last method is O(n), so in this case the whole loop will take O(2n)
Kamarey
@Kamarey: I think you mean O(n^2)
Jon Skeet
Ups, sure, it's O(n^2)
Kamarey
Yeah, must better to call c.Last() before the loop.
Greg
+2  A: 

You could use LINQ (if you use C#-3.0):

    foreach (Item i in items.Take(Items.Count - 1))
    {
...
    }
jdehaan
+2  A: 

As Jon Siegel pointed out:

...of course the notion of the last item in a collection is meaningless if the collection isn't indexed.

That said, suppose you want to do something for every item in an IEnumerable<T> except for one, that one being whichever happens to be the last one arbitrarily visited by an enumerator. Fine:

IEnumerator<Item> e = Items.GetEnumerator();
e.MoveNext();

while (e.Current != null)
{
    Item i = e.Current;
    // do something with i;

    if e.MoveNext()
    {
        // do another thing with i
    }
}
Dan Tao
A: 

i'd feel pretty dirty writing this but it might solve your problem.

Item last = null;

foreach (Item i in Items)
{
      last = i;
}

foreach (Item i in Items)
 {
      do something with i;

      if (i!=last){
            do another thing with i (but not if last item in collection);
      }
 }
lincolnk
Not the best way: Here you 1 more time loop through the Items collection, and in a case Item has some complex logic in Equals method, this will hurt the performance (this line: "if (i!=last){").
Kamarey
@Kamarey: That's a good explanation as to why you should "feel pretty dirty writing this".
Greg
+1  A: 

looks like this is what you were trying to solve.

List<string> list = getList();
string.Join(", ", list.ToArray());
tster
A: 

You can follow this logic as in button click event..

namespace LastEnumItem
{
    public partial class Form1 : Form
    {
        List<string> lst = new List<string>(); 
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            for(int i=0; i<=10 ; i++)
            {
                lst.Add("string " + i.ToString());
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string lastitem = lst[lst.Count-1];
            foreach (string str in lst)
            {
                if (lastitem != str)
                {
                    // do something
                }
                else
                {
                    MessageBox.Show("Last Item :" + str);
                }
            }
        }


    }
}
Jaswant Agarwal