2

わかりました、F# の学習を始めたばかりです。私は大学などで関数型言語にある程度触れていますが、F# などの言語での実際のプログラミングに関しては、まだかなり未熟です。

日常的に私は C# で作業していますが、今日は会社のコード ベースに時間を費やし、F# の観点から見る機会がありました。現実的なビジネス環境で言語の感触をつかむために、C# コードの一部を F# で書き直してみることにしました。

以下は、私が翻訳に苦労したいくつかの 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);
    }
} 

ループを「機能的な」方法で書き直そうとした結果、次のコードが得られましたが、それほど良いとは思いません。

let dataDict = 
      dict [ 
        for d in data 
          |> Seq.distinctBy(fun d -> d.Id) -> d.Id, 
             dict [                                                                                                   
                 for x in data |> Seq.filter(fun a -> a.Id = d.Id) -> x.Analysis, x
             ]
      ]

このコードにはいくつかの問題があります:

  • (ID、分析) ペアが重複している場合、警告は記録されず、さらに悪いことに
  • for と Seq.filter を使用して、データを (少なくとも) 2 回実行します。

どうすればこれを改善できますか? 私はそれをすべて間違っていますか?

4

2 に答える 2

1

あなたの要件を考えると、あなたが持っているものがおそらく最高です。パターン マッチングを使用して、コードを少し引き締めることができます。

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)
于 2015-06-26T21:27:46.770 に答える