Объединить несколько списков данных вместе по общему идентификатору в F # - PullRequest
7 голосов
/ 25 января 2011

У меня есть несколько списков данных из 4 разных источников с общим набором идентификаторов, которые я хотел бы объединить, основываясь на идентификаторе, в основном получая новый список, по одному для каждого идентификатора и одну запись для каждого источника .

Объекты в списке вывода из каждого из 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, причем первый столбец - это идентификатор, а coulmns 2 - 5 - данные из источников A - D, соответствующие идентификатору в этой строке.

Я совершенно новичок в F #, так как лучше всего обработать эти данные, чтобы я сопоставил все значения исходных данных по идентификатору ??

1 Ответ

8 голосов
/ 25 января 2011

Кажется, что вы можете просто объединить все списки, а затем использовать Seq.groupBy, чтобы получить список, содержащий уникальные идентификаторы в списках ввода и все значения, связанные с идентификатором. Это можно сделать, используя что-то вроде:

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)
...