This post was migrated from Justin’s personal blog, 'Codethinked.com.' Views, opinions, and colorful expressions should be taken in context, and do not necessarily represent those of Simple Thread (and were written under the influence of dangerous levels of caffeination).

If you want to learn all about LINQ, first go check out my series on TekPub and then come back here!

So, I blogged a while ago about the LINQ SelectMany operator. The LINQ SelectMany operator is one of the most useful, misunderstood, and underused operators in your LINQ repertoire. In my previous post I gave you a decent idea of what you can do with the LINQ SelectMany operator, but I’m not quite sure that I did a very good job at really showing you how it works. In this post, I want to give you a more visual explanation of the LINQ SelectMany operator, and what it can do for you.

A Visual Explanation of SelectMany

As I said in my previous post about the SelectMany operator, MSDN describes it like this: “Projects each element of a sequence to an IEnumerable<T> and flattens the resulting sequences into one sequence.” Again, once you are familiar with SelectMany, this is a great explanation, but it can still be a bit hard to visualize. So, let’s see…

1) it takes a sequence:

image

2) And then it iterates over each element in this sequence:

image

3) While it is iterating, it projects each element into an IEnumerable<T>:

image

4) And then flattens the resulting IEnumerables back into a single sequence:

image

Pretty easy to see  now, right? The SelectMany operator allows us to produce a single sequence with 1 to n items for each item in the original sequence. It really allows us to sort-of multiply each item in a sequence, or at least project it into multiple items. If we did something like this with Select then we would end up producing a sequence with multiple sub-sequences, like this:

image

While this might be useful, it is not exactly what we want in this case. We want a single contiguous sequence which we can then operate on using other LINQ operators.

Different Kinds Of Projections

Remember that all you have to do is get a list from each item in a list. You can do this by accessing a list that is on each item, like this:

image

Or you could do it by generating a list, for example, what if each item was an integer, we could generate a range based on each number:

image

Pretty cool, and powerful. It also lets us chain calls to SelectMany, like this:

image

So basically, it let’s you continue to generate n number of sequences, and then combine them all back together. Since each call to SelectMany generates a single sequence, then you can call SelectMany on that resulting sequence and continue to do so as many times as you want.

Summary

While most of the operators in LINQ let you get one output element for each element you have in your sequence, or they let you filter out elements, but SelectMany is the only operator that lets you produce n output elements for each element in your input sequence. This fact opens up all kinds of possibilities with LINQ that otherwise wouldn’t be available to you. I hope this helps you out!

18 Comments

Dave Ward

That last example is a really good one. Too many of the advanced LINQ examples are so esoteric that it’s hard to imagine applying them, but I can see myself needing that projection and probably would have done it a messier way than this before.

Reply
Tiendq

Thanks, your post is really useful, it helps me to understand SelectMany better and easier. But I think it’d be more useful if you provide some sample codes along with nice graphics.

Reply
Jon Fuller

Cool! Thanks man!

I’d been doing

customers.Map(x => x.Orders).Flatten()

(Map is my version of ‘Select’)

This will allow me to combine it into a simple one step process rather than 2… excellent.

Thanks again!

Reply
Hatim

I was pretty familiar with the selectMany operator but Love the diagrams 🙂 and a pretty good explanation!

Reply
Alex Ford

This is a very good explanation. I finally know what that dang method is for 😛

So just to re-iterate, I could use this to select all the comments on all my blog posts?

var allComments = _dataContext.Blogs.SelectMany(x => x.Comments);

Is that right?

Reply
Justin Etheredge

@Alex Sorry, I must have missed when you posted that comment! To answer your question, yes, that is exactly what it is used for.

Reply
Terry

Sweet! A picture is worth (new List {0, 100, 200, 300, 400, 500, 600, 700, 800, 900}).SelectMany(y => Enumerable.Range(y+1, 100)).Count() words!

Reply

Leave a Reply

Your email address will not be published. Required fields are marked *