Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/257.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/extjs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F#中的词典理解(?)(从C#转换)_C#_F#_Functional Programming_Dictionary Comprehension - Fatal编程技术网

F#中的词典理解(?)(从C#转换)

F#中的词典理解(?)(从C#转换),c#,f#,functional-programming,dictionary-comprehension,C#,F#,Functional Programming,Dictionary Comprehension,好吧,我刚开始学F。我曾在大学等地接触过函数式语言,但对于使用F#等语言进行的实际编程,我还是相当生疏的 我每天都在C#工作,但今天我有机会花一些时间研究公司的代码库,并从F#的角度来看待它。我决定尝试用F语言重写一些C代码,以便在现实的商业环境中感受这种语言 下面是我费劲翻译的一些C代码的释义: // MyData is a class with properties Id, Analysis, and some other relevant properties // Each pair o

好吧,我刚开始学F。我曾在大学等地接触过函数式语言,但对于使用F#等语言进行的实际编程,我还是相当生疏的

我每天都在C#工作,但今天我有机会花一些时间研究公司的代码库,并从F#的角度来看待它。我决定尝试用F语言重写一些C代码,以便在现实的商业环境中感受这种语言

下面是我费劲翻译的一些C代码的释义:

// MyData is a class with properties Id, Analysis, and some other relevant properties
// Each pair of (Id, Analysis) is (should be) distinct
IEnumerable<MyData> data = // fetch from DB...

// dataDict[id[analysis]] = MyData object (or "row") from DB
var dataDict = new Dictionary<String, Dictionary<String, MyData>> ();
foreach(var d in data)
{
    if(!dataDict.ContainsKey(d.Id))
        dataDict.Add(d.Id, new Dictionary<string, MyData>());

    if (dataDict[d.Id].ContainsKey(d.Analysis))
    {
        logger.Warn(String.Format("Id '{0}' has more than one analysis of type '{1}', 
            rows will be ignored", d.Id, d.Analysis));
    }
    else
    {
        dataDict[d.Id].Add(d.Analysis, d);
    }
} 
此代码有几个问题:

  • 如果存在重复(Id、分析)对,它不会记录警告,甚至更糟
  • 我使用for和Seq.filter对数据(至少)运行了两次

我该如何改进这一点?我做错了吗?

考虑到你的要求,你所拥有的可能是最好的。您可以使用模式匹配稍微收紧代码

let dataDict = Dictionary<_,Dictionary<_,_>>()
for d in data do
    match dataDict.TryGetValue(d.Id) with
    | true, m when m.ContainsKey(d.Analysis) ->
        (d.Id, d.Analysis)
        ||> sprintf "Id '%s' has more than one analysis of type '%s', rows will be ignored" 
        |> logger.Warn
    | true, m -> 
        m.Add(d.Analysis, d)
    | _ ->
        let m = Dictionary()
        m.Add(d.Analysis, d)
        dataDict.Add(d.Id, m)
let dataDict=Dictionary()
对于数据中的d,请执行以下操作:
将dataDict.TryGetValue(d.Id)与
|当m.ContainsKey(d.Analysis)->
(d.Id,d.Analysis)
||>sprintf“Id'%s'具有类型'%s'的多个分析,将忽略行”
|>记录器,警告
|是的,m->
m、 增加(d.分析,d)
| _ ->
设m=Dictionary()
m、 增加(d.分析,d)
数据目录添加(d.Id,m)

<>代码> < P> >我认为更具功能性的方法:

let intoMap (data: seq<MyData>) = 
    Seq.fold (fun (datamap, dups) (data: MyData) -> 
        match datamap |> Map.tryFind data.Id with
        | Some submap when submap |> Map.containsKey data.Analysis -> 
            datamap, data :: dups
        | Some submap ->
            let ext = Map.add data.Analysis data submap
            (Map.add data.Id ext datamap), dups
        | None ->
            let submap = Map.ofArray [| (data.Analysis, data) |]
            (Map.add data.Id submap datamap), dups
        ) (Map.empty, List.empty) data
let intoMap(数据:seq)=
Seq.fold(fun(datamap,dups)(数据:MyData)->
将datamap |>Map.tryFind data.Id与匹配
|当submap |>Map.containsKey data.Analysis->
数据映射,数据::dups
|一些子贴图->
设ext=Map.add data.Analysis data子映射
(Map.add data.Id ext datamap),dups
|无->
设submap=Map.ofArray[|(data.Analysis,data)|]
(Map.add data.Id submap datamap),dups
)(Map.empty,List.empty)数据
它是对数据的折叠,所以它只遍历序列一次。它的功能也更强大,因为它不会产生副作用——不是记录副本,而是收集副本并将其作为输出的一部分。以后你可以用它们做任何你喜欢的事

此外,我使用不可变映射而不是字典——我发现字典是F#代码中的一种代码味道。它提供的可变性在一些更深奥的场景中有其用途,但对于实际保存和传递数据,我只使用Map


这就是你当前问题的答案-但老实说,我可能会使用一个单独的函数来查找和拆分重复项,还有一个单独的函数,它可以在不考虑潜在重复的情况下构建一个映射,即使这意味着对数据进行多次传递。

您可以使用Seq.groupBy函数那些不是真正的字典理解-它们是列表理解,稍后将列表传递到函数中,从而生成字典。
let intoMap (data: seq<MyData>) = 
    Seq.fold (fun (datamap, dups) (data: MyData) -> 
        match datamap |> Map.tryFind data.Id with
        | Some submap when submap |> Map.containsKey data.Analysis -> 
            datamap, data :: dups
        | Some submap ->
            let ext = Map.add data.Analysis data submap
            (Map.add data.Id ext datamap), dups
        | None ->
            let submap = Map.ofArray [| (data.Analysis, data) |]
            (Map.add data.Id submap datamap), dups
        ) (Map.empty, List.empty) data