This is quite simple question but I didn't find an answer:
Is there any Seq/List operation in F# to match the LINQ SelectMany?
But if I try to prove that F# List operations are more powerful than LINQ...
In C# SelectMany usage syntax is pretty simple:
var flattenedList = from i in items1 from j in items2 select ...
Is there any easy direct match, List.flatten, List.bind or something like that?
SelectMany has a couple of signatures, but the most complex one seems to be:
IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>( this IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector );
In F# terms this would be:
('a -> 'b list) -> ('a -> 'b -> 'c) -> 'a list -> 'c list
collect
is the F# equivalent of SelectMany however it doesn't provide all the overloads. Here's how to make the one you referenced.
let selectMany (ab:'a -> 'b seq) (abc:'a -> 'b -> 'c) input = input |> Seq.collect (fun a -> ab a |> Seq.map (fun b -> abc a b)) // gives // val selectMany : ('a -> seq<'b>) -> ('a -> 'b -> 'c) -> seq<'a> -> seq<'c>
I believe F# doesn't provide all the SelectMany overloads because they would add noise to the library. Here's all four overloads to SelectMany in Microsoft Naming.
let selectMany (source : 'TSource seq) (selector : 'TSource -> 'TResult seq) = source |> Seq.collect selector let selectMany (source : 'TSource seq) (selector : 'TSource -> int -> 'TResult seq) = source |> Seq.mapi (fun n s -> selector s n) |> Seq.concat let selectMany (source : 'TSource) (collectionSelector : 'TSource -> 'TCollection seq) (resultSelector : 'TSource -> 'TCollection -> 'TResult) = source |> Seq.collect (fun sourceItem -> collectionSelector sourceItem |> Seq.map (fun collection -> resultSelector sourceItem collection)) let selectMany (source : 'TSource) (collectionSelector : 'TSource -> int -> 'TCollection seq) (resultSelector : 'TSource -> 'TCollection -> 'TResult) = source |> Seq.mapi (fun n sourceItem -> collectionSelector sourceItem n |> Seq.map (fun collection -> resultSelector sourceItem collection)) |> Seq.concat
"F# List operations are more powerful than LINQ..." While seq / list operations are great some real "F# power" comes from Function Composition and Currying.
// function composition let collect selector = Seq.map selector >> Seq.concat
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With