2012-11-20 10 views
5

Ho definito un tipo di record per alcuni dati del cliente in F # come segue: -somma condizionale in F #

type DataPoint = { 
     date: string; 
     dr: string; 
     Group: string; 
     Product: string; 
     Book: int; 
     Revenue: int} with 
      static member fromFile file = 
       file 
       |> File.ReadLines 
       |> Seq.skip 1 //skip the header 
       |> Seq.map (fun s-> s.Split ',') // split each line into array 
       |> Seq.map (fun a -> {date = string a.[0]; dr = string a.[1]; 
           Group = string a.[2]; Product = string a.[3]; 
           Book = int a.[4]; Revenue = int a.[5] });; 

    // creates a record for each line 
    let pivot (file) = DataPoint.fromFile file 
       |> ?????????? 

Per le righe in cui la data, dr, Gruppo e di prodotto sono tutti uguali, voglio poi sum tutte le voci Book and Revenue, producendo una riga ruotata. Quindi una sorta di dichiarazione if dovrebbe andare bene. Sospetto di dover iniziare dal primo punto dati e aggiungere in modo ricorsivo ogni riga corrispondente e quindi eliminare la riga corrispondente per evitare duplicati nell'output.

Dopo averlo fatto, sarò facilmente in grado di scrivere queste righe imperniate su un altro file csv.

Qualcuno può farmi iniziare?

risposta

7

Seq.groupBy e Seq.reduce sono quello che stai cercando:

let pivot file = 
    DataPoint.fromFile file 
    |> Seq.groupBy (fun dp -> dp.date, dp.dr, dp.Group, dp.Product) 
    |> Seq.map (snd >> Seq.reduce (fun acc dp -> 
          { date = acc.date; dr = acc.dr; 
          Group = acc.Group; Product = acc.Product; 
          Book = acc.Book + dp.Book; 
          Revenue = acc.Revenue + dp.Revenue; })) 
+0

Grande, questo è molto pulito. Testerà e accetterà se funziona. –

+0

Inoltre, grazie per aver segnalato le funzioni di cui ho bisogno per familiarizzare. –

+0

Prego :-). – pad

3

rapidamente hacked up, dovrebbe darvi un'idea:

// Sample data 
let data = [ 
      {date = "2012-01-01" 
       dr  = "Test" 
       Group = "A" 
       Product = "B" 
       Book = 123 
       Revenue = 123} 
      {date = "2012-01-01" 
       dr  = "Test" 
       Group = "A" 
       Product = "B" 
       Book = 123 
       Revenue = 123} 
      {date = "2012-01-01" 
       dr = "Test" 
       Group = "B" 
       Product = "B" 
       Book = 11 
       Revenue = 123}] 


let grouped = data |> Seq.groupBy(fun d -> (d.date, d.dr, d.Group, d.Product)) 
        |> Seq.map (fun (k,v) -> (k, v |> Seq.sumBy (fun v -> v.Book), v |> Seq.sumBy (fun v -> v.Revenue))) 

for g,books,revs in grouped do 
    printfn "Books %A: %d" g books 
    printfn "Revenues %A: %d" g revs 

stampe

Books ("2012-01-01", "Test", "A", "B"): 246 
Revenues ("2012-01-01", "Test", "A", "B"): 246 
Books ("2012-01-01", "Test", "B", "B"): 11 
Revenues ("2012-01-01", "Test", "B", "B"): 11 
+0

Ancora molto pulito e molto accurato. Li metterò alla prova entrambi. –