let inline project projection value = projection value, value
let projectToMap projection values = values |> Seq.map (project projection) |> Map.ofSeq
type XYZ = { X:int; Y:string; Z:float }
let xyzs = [{ X=3; Y="B"; Z=30.0 }
{ X=2; Y="A"; Z=10.0 }
{ X=1; Y="b"; Z=20.0 }
{ X=4; Y="a"; Z=20.0 }]
// just for demo purposes
let printXyzMap m =
m |> Map.iter (fun k { X=x; Y=y; Z=z } -> printfn "\t%A :: { X=%A; Y=%A; Z=%A }" k x y z)
stdout.WriteLine "by X:"
xyzs |> projectToMap (fun { X=x } -> x) |> printXyzMap
stdout.WriteLine "by Y:"
xyzs |> projectToMap (fun { Y=y } -> y) |> printXyzMap
stdout.WriteLine "by Z,Y:"
xyzs |> projectToMap (fun { Y=y; Z=z } -> z, y) |> printXyzMap
bGV0IGlubGluZSBwcm9qZWN0IHByb2plY3Rpb24gdmFsdWUgPSBwcm9qZWN0aW9uIHZhbHVlLCB2YWx1ZQpsZXQgcHJvamVjdFRvTWFwIHByb2plY3Rpb24gdmFsdWVzID0gdmFsdWVzIHw+IFNlcS5tYXAgKHByb2plY3QgcHJvamVjdGlvbikgfD4gTWFwLm9mU2VxCgp0eXBlIFhZWiA9IHsgWDppbnQ7IFk6c3RyaW5nOyBaOmZsb2F0IH0KbGV0IHh5enMgPSBbeyBYPTM7IFk9IkIiOyBaPTMwLjAgfQogICAgICAgICAgICB7IFg9MjsgWT0iQSI7IFo9MTAuMCB9CiAgICAgICAgICAgIHsgWD0xOyBZPSJiIjsgWj0yMC4wIH0KICAgICAgICAgICAgeyBYPTQ7IFk9ImEiOyBaPTIwLjAgfV0KCi8vIGp1c3QgZm9yIGRlbW8gcHVycG9zZXMKbGV0IHByaW50WHl6TWFwIG0gPQogICAgbSB8PiBNYXAuaXRlciAoZnVuIGsgeyBYPXg7IFk9eTsgWj16IH0gLT4gcHJpbnRmbiAiXHQlQSA6OiB7IFg9JUE7IFk9JUE7IFo9JUEgfSIgayB4IHkgeikKCnN0ZG91dC5Xcml0ZUxpbmUgImJ5IFg6Igp4eXpzIHw+IHByb2plY3RUb01hcCAoZnVuIHsgWD14IH0gLT4geCkgfD4gcHJpbnRYeXpNYXAKCnN0ZG91dC5Xcml0ZUxpbmUgImJ5IFk6Igp4eXpzIHw+IHByb2plY3RUb01hcCAoZnVuIHsgWT15IH0gLT4geSkgfD4gcHJpbnRYeXpNYXAKCnN0ZG91dC5Xcml0ZUxpbmUgImJ5IFosWToiCnh5enMgfD4gcHJvamVjdFRvTWFwIChmdW4geyBZPXk7IFo9eiB9IC0+IHosIHkpIHw+IHByaW50WHl6TWFw