Объединить несколько списков данных вместе с помощью общего идентификатора в F#
Вопрос
У меня есть несколько списков данных из 4 различных источников с общим набором идентификаторов, которые я хотел бы объединиться, на основе 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];
(Я понимаю, что этот код не является действительным, просто пытаясь дать основную идею ... списки фактически вытянуты и генерируются из базы данных)
Затем я хотел бы взять Soursea, Sourceb, Sourcec и поставлен и обработать их в список, содержащие объекты, что -то вроде этого:
type dataByID = {ID : int; valueA : decimal; valueB : decimal; valueC : decimal; valueD : decimal; }
... чтобы я мог затем распечатать их в CSV, причем первым столбцом является ID, а COULMNS 2 - 5 - данные из источников A - D, соответствующей идентификатору в этой строке.
Я совершенно новичок в F#, так что же будет лучшим способом обработки этих данных, чтобы я соответствовал всем значениям исходных данных с помощью ID ??
Решение
Кажется, что вы можете просто объединить все списки, а затем использовать 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
Операция карты для добавления индекса источника данных:
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)