{a, b, c, d...} Cartesian product of two sequences S1 and S2 is a sequence of all possible ordered pairs such that their first element is from S1 and the second is from S2. So, for example, if you have two sequences {a, b} and {x, y, z} , then their Cartesian product looks like {{a, x}, {a, y}, {a, z}, {b, x}, {b, y}, {b, z}} .SelectMany , in the “query syntax” it is a query with two “from” expressions:var s1 = new [ ] { a, b } ; <br/>
var s2 = new [ ] { x, y, z } ; <br/>
var product = <br/>
from first in s1 <br/>
from second in s2 <br/>
select new [ ] { first, second } ;{S1, S2, ... , Sn} is the sequence of all possible n-element sequences that have the first element of S1, the second of S2, and so on.{ { } } .{{a, b}} ) is the sequence of all possible single-element sequences, where the first (and only) element of {a, b} . Thus, the Cartesian product {{a, b}} is {{a}, {b}} .var product = <br/>
from first in s1 <br/>
from second in s2 <br/>
from third in s3 <br/>
select new [ ] { first, second, third } ;public static IEnumerable < IEnumerable < T >> CartesianProduct < T > ( this IEnumerable < IEnumerable < T >> sequences )sequences contains zero sequences, the job is done: we simply return { { } } .{a, b} and {x, y, z} ? We start by counting the Cartesian product of the first sequence. Let the inductive hypothesis be that we somehow did it, so we know the answer: {{a}, {b}} . How to connect {{a}, {b}} with {x, y, z} to get the total product?{{a}, {b}} and {x, y, z} are random {{{a}, x}, {{a}, y}, {{a}, z}, {{b}, x}, {{b}, y}, {{b},z}} , which is nonetheless seductively close to what we want to receive. We don't just want to find the Cartesian product {{a}, {b}} and {x, y, z} , creating a sequence containing {a} and x , but no, instead we need to calculate the Cartesian product by appending x to {a} to get {a, x} ! In other words, by concatenating {a} and {x} .{{a}, {b}} . We want to connect it with the sequence {x, y, z} :var newProduct = <br/>
from old in oldProduct <br/>
from item in sequence <br/>
select old. Concat ( new [ ] { item } } ;oldProduct is any Cartesian product, then we can calculate its combination with another sequence to get a new Cartesian product.{ { } } with the sequence {{a}, {b}} , we merge { } with {a} and { } with {b} to get {{a}, {b}} .static IEnumerable < IEnumerable < T >> CartesianProduct < T > ( this IEnumerable < IEnumerable < T >> sequences ) <br/>
{ <br/>
// : <br/>
IEnumerable < IEnumerable < T >> result = new [ ] { Enumerable. Empty < T > ( ) } ; <br/>
foreach ( var sequence in sequences ) <br/>
{ <br/>
var s = sequence ; // <br/>
// : SelectMany, <br/>
result = <br/>
from seq in result <br/>
from item in s <br/>
select seq. Concat ( new [ ] { item } ) ; <br/>
} <br/>
return result ; <br/>
}Aggregate method. It takes the starting value of the battery and the function that takes the last value and the current item and returns the new value of the battery. At the output of the method - the total value of the battery.static IEnumerable < IEnumerable < T >> CartesianProduct < T > ( this IEnumerable < IEnumerable < T >> sequences ) <br/>
{ <br/>
IEnumerable < IEnumerable < T >> emptyProduct = new [ ] { Enumerable. Empty < T > ( ) } ; <br/>
return sequences. Aggregate ( <br/>
emptyProduct, <br/>
( accumulator, sequence ) => <br/>
from accseq in accumulator <br/>
from item in sequence <br/>
select accseq. Concat ( new [ ] { item } ) ) ; <br/>
}(::) . In this case, to achieve the classical form of the Cartesian product, the initial sequence must be turned over before work begins.let product seqs =
List.rev seqs
|> List.fold
( fun acc cur ->
[ for seq in acc do
for item in cur do
yield item::seq]) [[]]Source: https://habr.com/ru/post/99128/
All Articles