views:

546

answers:

5

Is there a good way to enumerate through only a subset of a Collection in C#? That is, I have a collection of a large number of objects (say, 1000), but I'd like to enumerate through only elements 250 - 340. Is there a good way to get an Enumerator for a subset of the collection, without using another Collection?

Edit: should have mentioned that this is using .NET Framework 2.0.

+19  A: 

Try the following

var col = GetTheCollection();
var subset = col.Skip(250).Take(90);

Or more generally

public static IEnumerable<T> GetRange(this IEnumerable<T> source, int start, int end) {
  // Error checking removed
  return source.Skip(start).Take(end - start);
}

EDIT 2.0 Solution

public static IEnumerable<T> GetRange<T>(IEnumerable<T> source, int start, int end ) {
  using ( var e = source.GetEnumerator() ){ 
    var i = 0;
    while ( i < start && e.MoveNext() ) { i++; }
    while ( i < end && e.MoveNext() ) { 
      yield return e.Current;
      i++;
    }
  }      
}

IEnumerable<Foo> col = GetTheCollection();
IEnumerable<Foo> range = GetRange(col, 250, 340);
JaredPar
I love that extension method.
Daniel A. White
Sorry, this is using .NET 2.0; skip isn't available. If it was in .NET 3.5, this would be golden, though.
McWafflestix
@McWafflestix added a 2.0 solution
JaredPar
that does the trick in 2.0; not as concise as in 3.5, but it works.
McWafflestix
@McWafflestix, yes. One of the best things about LINQ is brevity
JaredPar
A: 

You might be able to do something with Linq. The way I would do this is to put the objects into an array, then I can choose which items I want to process based on the array id.

JD
A: 

If you find that you need to do a fair amount of slicing and dicing of lists and collections, it might be worth climbing the learning curve into the C5 Generic Collection Library.

Jekke
A: 

I like to keep it simple (if you don't necessarily need the enumerator):

for (int i = 249; i < Math.Min(340, list.Count); i++)
{
    // do something with list[i]
}
Fredrik Mörk
+2  A: 

Adapting Jared's original code for .Net 2.0:

IEnumerable<T> GetRange(IEnumerable<T> source, int start, int end)
{
    int i = 0;
    foreach (T item in source)
    {
        i++;
        if (i>end) yield break;
        if (i>start) yield return item;
    }
}

And to use it:

 foreach (T item in GetRange(MyCollection, 250, 340))
 {
     // do something
 }
Joel Coehoorn