-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #747 from polyadic/cartesian-product-docs
Update Out-of-date Cartesian Product Docs
- Loading branch information
Showing
1 changed file
with
40 additions
and
17 deletions.
There are no files selected for viewing
57 changes: 40 additions & 17 deletions
57
Documentation/src/enumerable-extensions/cartesian-product.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,38 +1,61 @@ | ||
## CartesianProduct | ||
|
||
In mathematics, specifically set theory, the Cartesian product of two sets A and B, denoted A×B, is the set of all ordered pairs (a, b) where a is in A and b is in B. | ||
In mathematics, specifically set theory, the Cartesian product of two sets A and B, denoted A×B, | ||
is the set of all ordered pairs (a, b) where a ∈ A and b ∈ B. | ||
|
||
The CartesianProduct extension function returns all possible pairs of two given IEnumerables. | ||
|
||
There are two overloads, one which lets you choose | ||
In other words: The Cartesian product produces all possible pairs of two given `IEnumerable`s. | ||
|
||
![cartesian-product with marbles](cartesian-product.svg "Marble me!") | ||
|
||
### Recipe | ||
The Cartesian product can be easily implemented ad-hoc using LINQ's built-in `SelectMany` extension function: | ||
|
||
```cs | ||
using System; | ||
using System.Linq; | ||
|
||
// Version A: Get each pair as a tuple | ||
var result = sequenceA.SelectMany(_ => sequenceB, ValueTuple.Create); | ||
|
||
// Version B: Transform each pair using a selector | ||
var result = sequenceA.SelectMany(_ => sequenceB, (a, b) => ...); | ||
|
||
// Version C: Using LINQs declarative query syntax | ||
var result = | ||
from a in sequenceA | ||
from b in sequenceB | ||
select ...; | ||
``` | ||
|
||
|
||
### Examples | ||
|
||
Two sequences as input: | ||
|
||
``` | ||
``` | ||
smiles = [😀, 😐, 🙄] | ||
fruits = [🍉, 🍌, 🍇, 🍓] | ||
``` | ||
``` | ||
|
||
The cartesian products of smiles and fruits: | ||
The Cartesian products of smiles and fruits: | ||
|
||
``` | ||
smiles × fruits => [[😀, 🍉], [😀, 🍌], [😀, 🍇], [😀, 🍓], | ||
[😐, 🍉], [😐, 🍌], [😐, 🍇], [😐, 🍓], | ||
``` | ||
smiles × fruits => [[😀, 🍉], [😀, 🍌], [😀, 🍇], [😀, 🍓], | ||
[😐, 🍉], [😐, 🍌], [😐, 🍇], [😐, 🍓], | ||
[🙄, 🍉], [🙄, 🍌], [🙄, 🍇], [🙄, 🍓]] | ||
``` | ||
|
||
In this C# example you see how all Playing cards are in fact a cartesian product of a suit and a value. | ||
In this C# example you see how all playing cards are in fact a Cartesian products of a suit and a value. | ||
|
||
This example uses the overload with our own selector, because we just want a sequence of strings. | ||
This example uses the overload with a selector, because we just want a sequence of strings. | ||
|
||
```cs | ||
var suits = ImmutableList.Create("♠", "♣", "♥", "♦"); | ||
var values = | ||
ImmutableList.Create("2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K", "A"); | ||
using System; | ||
using System.Linq; | ||
using Funcky; | ||
|
||
var suits = Sequence.Return("♠", "♣", "♥", "♦"); | ||
var values = Sequence.Return("2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K", "A"); | ||
|
||
var allCards = suits.CartesianProduct(values, (suit, value) => $"{value}{suit}"); | ||
``` | ||
var deck = suits.SelectMany(_ => values, (suit, value) => $"{value}{suit}"); | ||
``` |