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:
2) And then it iterates over each element in this sequence:
3) While it is iterating, it projects each element into an IEnumerable<T>:
4) And then flattens the resulting IEnumerables back into a single sequence:
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:
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:
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:
Pretty cool, and powerful. It also lets us chain calls to SelectMany, like this:
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!
Loved the article? Hated it? Didn’t even read it?
We’d love to hear from you.
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.
Hey Justin,
which tool do you use for illustration ?
Thanks
@Camal Just Microsoft Powerpoint 2007.
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.
Great diagrams!
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!
I was pretty familiar with the selectMany operator but Love the diagrams 🙂 and a pretty good explanation!
A picture is worth a thousand words
Thank you
Sisirak
Nice job! Love the visual representations. They really "speak to me" 🙂
Awesome post! Thanks!
Nice explanation, thank you.
I like you visualization skills. Very cool post. Thank you!
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?
@Alex Sorry, I must have missed when you posted that comment! To answer your question, yes, that is exactly what it is used for.
Gr8 illustration. Thanks!
Great article and diagrams. Thank you!
Very nice explanation
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!