How to do linq-to-IEnumerable-style joins in F#
I've got a project that I'm trying to convert to F#, with a fair amount of linq-to-IEnumerable style queries in it. I'm curious what the most elegant way of doing a join of multiple lists would be in F#. For instance if I have a bunch of C# code like the following
var joinedList =
from val1 in list1
join val2 in list2 on val1.Key equals val2.Parent
join val3 in list3 on val1.Key equals val3.Parent
orderby val1
select new {val1, val2, val3};
what would be the best way to translate this to F#? I'll leave open the definition of "best", but I'm looking for something functional rather than imperative, and preferably without converting my lists to seqs and/or importing System.Linq. Both lazy and eager solutions would be useful. And of course reusability is key, since I have queries like this all over. If there's any way of using workflows to make t开发者_Go百科he syntax more elegant, that would be great too.
Well, in Don's blog about LINQ and the Powerpack:
Link
it shows off how to do LINQ join calls. But of course that's on seq
s and using LINQ. He also points out that a join is like a conditional. So I think e.g. your example is like
let joinedList = [
for v1 in l1 do
for v2 in l2 do
if v1.Key = v2.Parent then
for v3 in l3 do
if v1.Key = v3.Parent then
yield (v1, v2, v3)] |> List.sort
though I haven't verified it on real data.
A first attempt using pipelines on a simplified version (ignore list3
):
let res = list1
|> Seq.collect (fun v1 -> Seq.filter (fun v2 -> v1.Key = v2.Parent) list2 |> Seq.map (fun v2 -> (v1,v2))
|> Seq.sortBy (fun (x,y) -> x)
which will leave a IEnumerable<Tuple<T1,T2>>
. A second collect and map would join the third list
精彩评论