2012-11-20 26 views
5

ich einen Datensatztyp für einige Client-Daten in F # definiert sich wie folgt: -Conditional Summe 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 
       |> ?????????? 

Für die Zeilen, in denen Datum, dr, Gruppe und Produkt alle gleich sind, möchte ich dann Summe alle Buch- und Einnahmeneinträge, die eine geschwungene Reihe erzeugen. Also sollte irgendeine Art von if else-Anweisung in Ordnung sein. Ich vermute, ich muss am ersten Datenpunkt beginnen und rekursiv jede passende Zeile hinzufügen und dann die passende Zeile löschen, um Duplikate in der Ausgabe zu vermeiden.

Sobald ich dies getan habe, werde ich leicht in der Lage sein, diese geschwenkten Zeilen in eine andere CSV-Datei zu schreiben.

Kann mich jemand anfangen?

Antwort

7

Seq.groupBy und Seq.reduce sind das, was Sie suchen:

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

Große, das ist sehr gepflegt. Wird testen und akzeptieren, wenn es funktioniert. –

+0

Danke auch für das Aufzeigen der Funktionen, mit denen ich mich vertraut machen muss. –

+0

Gern geschehen :-). – pad

3

schnell gehackt, sollten Sie eine Vorstellung geben:

// 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 

druckt

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

Wieder sehr gepflegt und sehr gründlich. Ich werde beide testen. –