LINQ SelectMany in Depth
Tags: csharp, linq, dotnet
Published: 2020-01-27 07:08:58

---
title: LINQ SelectMany in Depth
published: true
date: 2020-01-27 07:02:31 UTC
tags: csharp,LINQ,dotnet
cover_image: https://i2.wp.com/killalldefects.com/wp-content/uploads/2020/01/SelectManyWithIndex.png
series: LINQ
canonical_url: https://killalldefects.com/2020/01/27/linq-selectmany-in-depth/
---

In this article, I’ll walk through the various overloads and usages of LINQ’s `SelectMany` methods.

`SelectMany` is in many ways the opposite of `GroupBy` which I covered [last time](https://killalldefects.com/2020/01/21/dotnet-linq-groupby-in-depth/) in this series on LINQ. While `GroupBy` took a single collection and transformed it into multiple child collections, `SelectMany` flattens child collections into a single merged collection.

So, how is this flattening actually useful?

## Basic SelectMany Operations

Imagine you had a collection of books. Each book may have one or more characters in it (think people, not letters).

If I wanted to enumerate my entire library and identify every character – regardless of book – that’s more or less what `SelectMany` does on a collection basis.

Put another way, `SelectMany` maps an enumerable property on each item in a collection into a single flat list.

The most simple form of this code looks like this:

```cs
var people = books.SelectMany(b => b.Characters);
```

This operation would return a list of characters that might look something like this (comments added for ease of understanding):

```json
[
  // Characters from Sphere
  "Harry",
  "Norman",
  "Beth",
  "Jerry",
  // Characters from Jurassic Park
  "Malcolm",
  "Grant",
  "Satler",
  "Nedry",
  "Hammond",
  "Gennaro",
  "Tim",
  "Lex"
]
```

Note that the resulting collection is a single flat collection, not multiple groups of collections. This makes `SelectMany` nearly the inverse operation to the `GroupBy` method.

The function we provided `SelectMany` for identifying the nested collection is called the _collection selector_.

## Adding Result Selectors

LINQ also provides an additional overload that gives us something called a _result selector_.

The result selector is a simple function that transforms an individual node in the collection that would be returned into something different. It does this via a function that takes in the parent collection (think book, using the analogy before) as well as the child in that collection (think character in the same example).

Take a look at what this looks like, using `(b, c)` as inputs to a function that returns a new anonymous type containing a book and character:

![](https://i0.wp.com/killalldefects.com/wp-content/uploads/2020/01/SelectManyResultSel1.png?fit=770%2C185&ssl=1)

The resulting collection now provides a bit more context on each character, as listed below in this abbreviated sample:

```json
[
  {
    "Book": "Sphere",
    "Character": "Harry"
  },
  // Some results omitted
  {
    "Book": "Jurassic Park",
    "Character": "Lex"
  }
]
```

Note that you don’t need to return an object at all. Since characters are strings in our example, we can just as easily do some string formatting operations as follows:

![](https://i2.wp.com/killalldefects.com/wp-content/uploads/2020/01/SelectManyResultSel2-4.png?fit=770%2C118&ssl=1)

This simpler code results in a far more concise and readable output:

```json
[
  "Harry (Sphere)",
  "Norman (Sphere)",
  "Beth (Sphere)",
  "Jerry (Sphere)",
  "Malcolm (Jurassic Park)",
  "Grant (Jurassic Park)",
  "Satler (Jurassic Park)",
  "Nedry (Jurassic Park)",
  "Hammond (Jurassic Park)",
  "Gennaro (Jurassic Park)",
  "Tim (Jurassic Park)",
  "Lex (Jurassic Park)"
]
```

Pretty cool, right?

As we saw, not only can `SelectMany` flatten nested collections into a single collection, it can also transform or map the objects in those collections into different objects as needed.

## Index-Based Overloads

Sometimes you need to know what index an item is in the source collection. This case _should_ be somewhat rare and typically involves cases where you have to join together two different sources of data.

For this case, LINQ provides overloads for both of the methods we’ve discussed so far. Each overload allows you to add in a function parameter to the _collection selector_ that will take in the integer-based index of that collection.

To take a look at what this might look like, see the following example:

![](https://i0.wp.com/killalldefects.com/wp-content/uploads/2020/01/SelectManyWithIndex-1.png?w=770&ssl=1)

Here the `b` parameter in the collection selector corresponds to the `Book` object while the `i` parameter is the zero-based index in the collection. We grab the characters list out of the `characters` collection by index and `SelectMany` is able to use its _results selector_ on the resulting object.

Again, this is a somewhat uncommon overload to use but it can be helpful in cases where your data is fragmented across multiple collections.

## Closing Thoughts

In my opinion, `SelectMany` is much more useful than the inverse operation, `GroupBy`.

I would strongly consider `SelectMany` anytime you need to flatten nested lists into a single collection.

Additionally, the ability to flatten and transform a collection in a single method call is extremely efficient (at the cost of readability) and can reduce the need to chain together subsequent LINQ calls to transform the result collection.

Ultimately, I feel you will use `SelectMany` on an infrequent yet reliable basis for its utility value alone when dealing with nested collections. The mapping functions may be less needed, but still important in key scenarios.

If anything in this article was confusing, please let me know or check out [Microsoft’s own documentation](https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.selectmany) on the method group.

If you’ve found a use for `SelectMany` I haven’t covered here, I’d love to add it to my own bag of tricks. Please leave a comment and let me know what you’ve found.

The post [LINQ SelectMany in Depth](https://killalldefects.com/2020/01/27/linq-selectmany-in-depth/) appeared first on [Kill All Defects](https://killalldefects.com).