通过F#中的公共ID将多个数据列表合并在一起

时间:2011-01-24 21:12:25

标签: f# f#-data

我有4个不同来源的多个数据列表,其中有一组共同的ID,我希望根据ID合并在一起,基本上以新列表结束,每个ID一个,每个来源一个条目

来自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是源A-D的数据,对应于该行的ID。

我对F#完全不熟悉,那么处理这些数据的最佳方法是什么,以便我按ID匹配所有源数据值?

1 个答案:

答案 0 :(得分:8)

似乎您可以简单地连接所有列表,然后使用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) }

如果要关联源(无论是data1data2, 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)