既存のコードで 2 つの配列をマージすると、より均一な動作になる場合があります。特に必要でない限り (たとえば、basearr に重複が含まれている場合にプログラムをクラッシュさせたい場合)、uniform の方が優れています。
let incrementalAdderImperative aseq =
let d= System.Collections.Generic.Dictionary<_,_>()
Seq.iter(fun (k,v) -> if d.ContainsKey(k)
then d.[k] <- d.[k] + v
else d.Add(k,v)) aseq
あなたの質問に答えるには:
リストが長い場合 (たとえば、それぞれ約 30000)、パフォーマンスの観点からこのようにすることは賢明ですか?
Dictionary クラスに依存して、ハッシュベースの辞書を使用しています。したがって、まったく劣化しないはずです。これは、IDictionary で説明されている辞書の機能ではなく、辞書のこの実装のプロパティであることに注意してください。他の実装があります (たとえば Map)
パフォーマンスが気になる場合は、内部のサイズ変更を避けるために、発生するキーの数を (高速に) 推定して辞書を初期化する必要があります。使用されている具体的なタイプを知っている(ハッシュベースの辞書など)
(各データ リストの列 1 で) 日付で並べ替えてから、より命令的なアプローチを使用する方がよいでしょうか?
日付順にソートすると、折りたたむことができます。これはもっと速いと思いますが、あなたが言及した数はそれほど大きくありません。
let oneshotAdder reducer kvArr =
kvArr |> Array.sortInPlaceBy fst
let a = kvArr
|> Array.fold(fun (res) (k,v) ->
match res with
| [] -> (k,v)::res
| ((prevk,_)::xs) when k = prevk -> (k,reducer v (List.head res |> snd))::(List.tail res)
| _ -> (k,v)::res)
List.empty
dict a
let data = Array.concat ([basearr; lookarr] |> List.map List.toArray)
let dict2 = oneshotAdder (+) data
ps : あなたが与えた例では、 basearr と lookarr は配列ではなくリストであるため、実際に配列を操作したいと仮定すると無関係な操作になります。
f# または c# には sth ビルドさえありますか?
F# では、groupby をネイティブに実行して要素を合計できます。コレクション変換の本質は、関数を渡すことなので、それをネイティブに持っていても不思議ではありません。C# では、Linq を使用してそのような列挙変換を取得できます。これは、内部では fsharp のようないくつかの関数にマップされます。
let groupByAdder reducer (kvArr:('k*'v) array) =
kvArr |> Seq.groupBy fst
|> Seq.map (fun (k,vs) -> k , vs |> Seq.map snd |> (Seq.reduce reducer))
|> dict
let dict3 = groupByAdder (+) data