質問
IDに基づいてマージしたい共通のIDセットを備えた4つの異なるソースからのデータの複数のリストがあり、基本的には新しいリスト、各IDの1つ、ソースごとに1つのエントリになります。
4つのソースのそれぞれの出力リストのオブジェクトは、次のようになります。
type data = {ID : int; value : decimal;}
だから、たとえば私は持っているでしょう:
let sourceA = [data1, data2, data3];
let sourceB = [data1, data2, data3];
let sourceC = [data1, data2, data3];
let sourceD = [data1, data2, data3];
(このコードは無効ではなく、基本的なアイデアを与えようとしているだけです...リストは実際にデータベースから引き出され、生成されます)
その後、SourCea、SourceB、Sourcecを使用してSourcedを使用して、このようなものを含むオブジェクトを含むリストにそれらを処理したいと思います。
type dataByID = {ID : int; valueA : decimal; valueB : decimal; valueC : decimal; valueD : decimal; }
...その後、CSVでそれらを印刷できるように、最初の列はIDであり、Coulmns 2-5はその行のIDに対応するソースA -Dからのデータです。
私はF#にまったく初めてなので、このデータを処理するための最良の方法は何ですか?
解決
すべてのリストを単純に連結してから使用できるようです Seq.groupBy
入力リストに一意のIDを含むリストとIDに関連付けられたすべての値を取得するには。これは、次のようなものを使用して実行できます。
let data =
[ data1; data2; data3; data4 ] // Create list of lists of items
|> Seq.concat // Concatenate to get a single list of items
|> Seq.groupBy (fun d -> d.ID) // Group elements by ID
seq { for id, values in data ->
// ID is the id and values is a sequence with all values
// (that come from any data source) }
ソースを関連付けたい場合(それがあったかどうか data1
, data2, etc...) with the value then you can first use
データソースのインデックスを追加するためのmap`操作:
let addIndex i data =
data |> Seq.map (fun v -> i, v)
let data =
[ List.map (addIndex 1) data1;
List.map (addIndex 2) data2;
List.map (addIndex 3) data3;
List.map (addIndex 4) data4 ]
|> Seq.concat
|> Seq.groupBy (fun (index, d) -> d.ID)
今、 data
また、データソースのインデックス(1から3)も含まれているため、値を繰り返すと、インデックスを使用して、アイテムがどのデータソースから来ているかを調べることができます。より良いバージョンを使用して書くことができます Seq.mapi
データソースのリストを反復し、すべての値にインデックスを自動的に追加するには:
let data =
[ data1; data2; data3; data4 ]
|> Seq.mapi (fun index data -> Seq.map (addIndex index) data)
|> Seq.concat
|> Seq.groupBy (fun (index, d) -> d.ID)