Reputation: 12107
I have 2 lists with coordinates (one per axis) and I'm making squares out of them:
// create all combinations
let squares = List<int * int * int * int>()
seqX
|> Seq.pairwise
|> Seq.iter (fun (x1, x2) ->
seqY
|> Seq.pairwise
|> Seq.iter (fun (y1, y2) -> squares.Add(x1, y1, x2, y2))
)
Is there a way, using the collection functions to make this? I can't use Seq.map because the output will not match the total number of iterations
|> Seq.map (fun (y1, y2) -> (x1, y1, x2, y2))
will not work
Upvotes: 1
Views: 115
Reputation: 12667
You could use Seq.collect
to flat-map an inner sequence.
Collect (aka SelectMany
in LINQ, and flatMap
in JS) projects each item onto a new sequence, and flattens the results.
seqX
|> Seq.pairwise
|> Seq.collect(fun (x1, x2) -> seqY |> Seq.map(fun (y1, y2) -> (x1, x2, y1, y2))
Or you could make a sequence expression to do it for you, which de-sugars to the above:
seq {
for (x1, x2) in seqX |> Seq.pairwise do
for (y1, y2) in seqY |> Seq.pairwise do
yield (x1, x2, y1, y2)
}
Sequence expressions are very useful when there is depth involved.
It's much cleaner than writing nested closures for every level (seq |> Seq.collect (fun _ -> Seq.collect(fun...
).
Here's an example which finds all right-angled triangles whose sides are less than 10, by going through every possible triangle and checking Pythagoras' theorem.
seq {
let sides = [1..10]
for a in sides do
for b in sides do
for c in sides do
if a * a + b * b = c * c then
yield (a, b, c)
}
This would be much uglier de-sugared.
Upvotes: 5