该算法已经存在高阶函数?

时间:2017-02-26 06:35:36

标签: collections f# higher-order-functions

我已经想出了我在F#代码中需要的这个简单的算法(将元组列表转换为列表键的映射集合):

let MergeIntoMap<'K,'V when 'K: comparison>(from: seq<'K*'V>): Map<'K,seq<'V>>=
    let keys = from.Select(fun (k,v) -> k)
    let keyValuePairs = seq {
        for key in keys do
            let valsForKey = from.Where(fun (k,v) -> key = k).Select(fun (k,v) -> v) |> seq
            yield key,valsForKey
    }
    keyValuePairs |> Map.ofSeq

示例输入:

[ ("a", 1); ("b", 2), ("a", 3) ]

输出:

dict [ ("a", [1; 3]), ("b", [2]) ]

我认为这必须是BCL或F#的高阶函数中的一部分吗?如果是,有人可以引用我吗?因为我确定我的代码效率不高,因为它......

1 个答案:

答案 0 :(得分:3)

似乎你想得到类似的东西

let toGroupMap x = 
    x
    |> Seq.groupBy fst 
    |> Seq.map 
        (fun (k,v) -> k, v |> Seq.map snd |> Seq.toArray)
    |> Map.ofSeq

FSI:

val toGroupMap : x:seq<'a * 'b> -> Map<'a,'b []> when 'a : comparison
val input : (string * int) list = [("a", 1); ("b", 2); ("a", 3)]
val output : Map<string,int []> = map [("a", [|1; 3|]); ("b", [|2|])]

修改

在评论中写了Fyodor Soikin,有一种扩展方法ToLookup,它可能会满足您的需求。

open System.Linq

let output = input.ToLookup(fst, snd)

您可以阅读here关于ILookup和IDictionary接口之间的区别