2012-11-20 14 views
5

I zdefiniowano typ rekordu dla niektórych danych klienta w F # w następujący sposób: -Warunkowe suma w 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 
       |> ?????????? 

Dla wierszy, gdzie data, dr, Grupa i produktów są równi, chcę następnie suma wszystkie pozycje Księgi i Przychody, generujące wiersz przechylony. Więc jakaś instrukcja if if else powinna być w porządku. Podejrzewam, że muszę zacząć od pierwszego punktu danych i rekurencyjnie dodać każdy pasujący wiersz, a następnie usunąć pasujący wiersz, aby uniknąć duplikatów w danych wyjściowych.

Kiedy to zrobię, będę mógł łatwo zapisać te obrócone wiersze w innym pliku CSV.

Czy ktoś może mnie uruchomić?

Odpowiedz

7

Seq.groupBy i Seq.reduce to, czego szukasz:

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

Wielkiego, to jest bardzo schludny. Testuje i akceptuje, jeśli działa. –

+0

Dziękuję również za wskazanie funkcji, które muszę poznać. –

+0

Nie ma za co :-). – pad

3

Szybko włamał się powinno dać pewne wyobrażenie:

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

wydruki

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

Znów bardzo schludny i bardzo dokładny. Testuję oba te elementy. –