24

We have a simple structure which is just a list of lists, like so...

var fooInfo = new List<List<Foo>>();

I'm wondering if there's a simple way we can use linq to return the total of all items from the inner lists. For example, if we had this...

fooInfo.add(new List<Foo>()); // First list within the outer list
fooInfo.add(new List<Foo>()); // Second list within the outer list
fooInfo.add(new List<Foo>()); // Third list within the outer list

// Add two items to the first inner list
fooInfo[0].add(new Foo());
fooInfo[0].add(new Foo());

// Add one item to the second inner list
fooInfo[1].add(new Foo());

// Add four items to the third inner list
fooInfo[2].add(new Foo());
fooInfo[2].add(new Foo());
fooInfo[2].add(new Foo());
fooInfo[2].add(new Foo());

...we would have three lists with two, one and four items respectively, meaning the total 'Foo' objects are seven. That's the number I'm hoping to retrieve via linq rather than having to write our own looping code and manually tally them up.

e.g.

var totalFoos = fooInfo.LINQToGetTotalFoos();

rather than....

int totalFoos = 0;

foreach(var childList in fooInfo)
    totalFoos += childList.Count();
Mark A. Donohoe
  • 28,442
  • 25
  • 137
  • 286

2 Answers2

32

A simple Enumerable.Sum would suffice.

var totalFoos = fooInfo.Sum(childList => childList.Count); 

It computes the sum of the sequence of Int32 values that are obtained by invoking a transform function on each element of the input sequence.

You can use SelectMany but performance of this would be better.

Mark A. Donohoe
  • 28,442
  • 25
  • 137
  • 286
Nikhil Agrawal
  • 47,018
  • 22
  • 121
  • 208
  • 1
    I'm almost embarrassed it was so simple and I didn't think of it! (And yes, I realize I'm adding this comment almost seven years after I asked and accepted it. Someone voted this up and made me come back. lol) – Mark A. Donohoe Mar 05 '21 at 22:38
11

Use SelectMany and Count:

var nbOfItems = source.SelectMany(x => x).Count();

or Select, Count and Sum:

var nbOfItems = source.Select(x => x.Count()).Sum();

The latter will perform better, because it will not enumerate over all the items like SelectMany will.

MarcinJuraszek
  • 124,003
  • 15
  • 196
  • 263
  • @NikhilAgrawal `Enumerable.Count()` checks if the target implements `ICollection` (and because of that has `Count` property), and uses it if it does. – MarcinJuraszek Jul 14 '14 at 05:19
  • Yes. Valid point. My concern was to use `List.Count` instead of `IEnumerable.Count`. That would make your queries lighter. – Nikhil Agrawal Jul 14 '14 at 05:26
  • Read this http://stackoverflow.com/questions/981254/is-the-linq-count-faster-or-slower-than-list-count-or-array-length – Nikhil Agrawal Jul 14 '14 at 05:27