32

Whats the best/easiest way to obtain a count of items within an IEnumerable collection without enumerating over all of the items in the collection?

Possible with LINQ or Lambda?

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
Sean Chambers
  • 8,572
  • 7
  • 41
  • 55
  • 1
    possible duplicate of [Howto: Count the items from a IEnumerable without iterating?](http://stackoverflow.com/questions/168901/howto-count-the-items-from-a-ienumerablet-without-iterating) – Chris Pietschmann Feb 18 '12 at 15:22

11 Answers11

20

In any case, you have to loop through it. Linq offers the Count method:

var result = myenum.Count();
Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
17

The solution depends on why you don't want to enumerate through the collection.

If it's because enumerating the collection might be slow, then there is no solution that will be faster. You might want to consider using an ICollection instead if possible. Unless the enumeration is remarkably slow (e.g. it reads items from disk) speed shouldn't be a problem though.

If it's because enumerating the collection will require more code then it's already been written for you in the form of the .Count() extension method. Just use MyEnumerable.Count().

If it's because you want to be able to enumerate the collection after you've counted then the .Count() extension method allows for this. You can even call .Count() on a collection you're in the middle of enumerating and it will carry on from where it was before the count. For example:

foreach (int item in Series.Generate(5))
{
    Console.WriteLine(item + "(" + myEnumerable.Count() + ")");
}

will give the results

0 (5)

1 (5)

2 (5)

3 (5)

4 (5)

If it's because the enumeration has side effects (e.g. writes to disk/console) or is dependant on variables that may change between counting and enumerating (e.g. reads from disk) [N.B. If possible, I would suggest rethinking the architecture as this can cause a lot of problems] then one possibility to consider is reading the enumeration into an intermittent storage. For example:

List<int> seriesAsList = Series.Generate(5).ToList();

All of the above assume you can't change the type (i.e. it is returned from a library that you do not own). If possible you might want to consider changing to use an ICollection or IList (ICollection being more widely scoped than IList) which has a Count property on it.

Community
  • 1
  • 1
ICR
  • 13,896
  • 4
  • 50
  • 78
16

You will have to enumerate to get a count. Other constructs like the List keep a running count.

kame
  • 20,848
  • 33
  • 104
  • 159
Brian Leahy
  • 34,677
  • 12
  • 45
  • 60
6

Use this.

IEnumerable list =..........;

list.OfType<T>().Count()

it will return the count.

C. A. McCann
  • 76,893
  • 19
  • 209
  • 302
Mukesh
  • 69
  • 1
  • 1
1

There's also IList or ICollection, if you want to use a construct that is still somewhat flexible, but also has the feature you require. They both imply IEnumerable.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
1

An IEnumerable will have to iterate through every item. to get the full count. If you just need to check if there is one or more items in an IEnumerable a more efficient method is to check if there are any. Any() only check to see there is a value and does not loop through everything.

IEnumerable myStrings = new List(){"one","two", "three"};

bool hasValues = myStrings.Any();

Timmy Fuller
  • 75
  • 1
  • 10
1

It also depends on what you want to achieve by counting.. If you are interested to find if the enumerable collection has any elements, you could use

myEnumerable.Any() over myEnumerable.Count() where the former will yield the first element and the later will yield all the elements.

0

Not possible with LINQ, as calling .Count(...) does enumerate the collection. If you're running into the problem where you can't iterate through a collection twice, try this:

List<MyTableItem> myList = dataContext.MyTable.ToList();
int myTableCount = myList.Count;

foreach (MyTableItem in myList)
{
   ...
}
Greg Hurlman
  • 17,666
  • 6
  • 54
  • 86
0

If you need to count and then loop you may be better off with a list.

If you're using count to check for members you can use Any() to avoid enumerating the entire collection.

Keith
  • 150,284
  • 78
  • 298
  • 434
0

The best solution -as I think is to do the following:

  1. using System.Linq.Dynamic;
  2. myEnumerable.AsQueryable().Count()
  • 4
    Wrong. That no better than anything else, and probably worse. – SLaks Jan 06 '11 at 22:24
  • Still the same.. what if we only need the Count, and because we don't want to iterate to each record.. Why? because we want fast.. – nrs Mar 26 '20 at 05:32
0

When I want to use the Count property, I use ILIST which implements IEnumerable and ICollection interfaces. The ILIST data structure is an Array. I stepped through using the VS Debugger and found that the .Count property below returns the Array.Length property.

IList<string> FileServerVideos = Directory.GetFiles(VIDEOSERVERPATH, "*.mp4"); 
if (FileServerVideos.Count == 0)
    return;
Mike Meinz
  • 506
  • 3
  • 9