2011-01-24 13 views
7

Tengo varias listas de datos de 4 fuentes diferentes con un conjunto común de ID que me gustaría fusionar, basado en ID, que básicamente termina en una nueva lista, uno para cada ID y una entrada única para cada fuente.Fusionar múltiples listas de datos por ID común en F #

Los objetos en la lista de salida de cada una de las 4 fuentes tienen el siguiente aspecto:

type data = {ID : int; value : decimal;} 

así, por ejemplo, me gustaría tener:

let sourceA = [data1, data2, data3]; 
let sourceB = [data1, data2, data3]; 
let sourceC = [data1, data2, data3]; 
let sourceD = [data1, data2, data3]; 

(Me doy cuenta de que este código no es válido, simplemente tratando de dar una idea básica ... las listas son realmente extraídas y generadas desde una base de datos)

Me gustaría tomar sourceA, sourceB, sourceC y sourceD y procesarlas en una lista que contiene los objetos algo como esto:

type dataByID = {ID : int; valueA : decimal; valueB : decimal; valueC : decimal; valueD : decimal; } 

... así que puedo entonces imprimirlos en un CSV, con la primera columna es el ID y coulmns 2 - 5 siendo los datos de fuentes A - D correspondiente a la ID en esa fila.

Soy totalmente nuevo en F #, entonces, ¿cuál sería la mejor manera de procesar estos datos para que coincida con todos los valores de datos de origen por ID?

Respuesta

8

Parece que podría concatenar todas las listas y luego usar Seq.groupBy para obtener una lista que contenga ID únicos en las listas de entrada y todos los valores asociados con la ID. Esto se puede hacer usando algo como:

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

Si desea asociar la fuente (si era data1, operación data2, etc...) with the value then you can first use map` añadir un índice de la fuente de datos:

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) 

Ahora, data también contiene un índice del origen de datos (de 1 a 3), por lo que al iterar sobre los valores, puede usar el índice para averiguar de qué fuente proviene el elemento. Incluso una versión más agradable puede escribirse usando Seq.mapi para iterar sobre la lista de las fuentes de datos y agregue el índice a todos los valores automáticamente:

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) 
+0

como dije, totalmente nuevo para F # ... Creo que tengo la idea básica, pero un ejemplo de código rápido sería extremadamente útil. –

+0

@Adam: Agregué algunos ejemplos :-) –

Cuestiones relacionadas