Search code examples
f#webclientsequences

F# read from file vs download string and split by newline


I am new to F# and trying to solve this Kata

The file football.dat contains the results from the English Premier League for 2001/2. The columns labeled ‘F’ and ‘A’ contain the total number of goals scored for and against each team in that season (so Arsenal scored 79 goals against opponents, and had 36 goals scored against them). Write a program to print the name of the team with the smallest difference in ‘for’ and ‘against’ goals.

When save the file and and the read it using File.ReadAllLines, my solutons works:

open System.IO
open System

let split (s:string) =
    let cells = Array.ofSeq(s.Split([|' '|],StringSplitOptions.RemoveEmptyEntries))    
    (cells.[1], int cells.[6], int cells.[8])

let balance t = 
    let (_,f,a) = t
    -(f-a)

let lines = List.ofSeq(File.ReadAllLines(@"F:\Users\Igor\Downloads\football.dat"));;


lines      
    |> Seq.skip 5       
    |> Seq.filter (fun (s:string) -> s.Split([|' '|],StringSplitOptions.RemoveEmptyEntries).Length = 10)    
    |> Seq.map split    
    |> Seq.sortBy balance    
    |> Seq.take 1
    |> Seq.map (fun (n,_,_) -> printfn "%s" n)

but when instead of reading the file I download it using WebClient and split lines the rest of the code does not work. The sequence is the same length but F# Interactive does not show the elements and prints no output. The code is

open System.Net
open System

let split (s:string) =
    let cells = Array.ofSeq(s.Split([|' '|],StringSplitOptions.RemoveEmptyEntries))    
    (cells.[1], int cells.[6], int cells.[8])

let balance t = 
    let (_,f,a) = t
    -(f-a)

let splitLines (s:string) = 
    List.ofSeq(s.Split([|'\n'|]))


let wc = new WebClient()
    let lines = wc.DownloadString("http://pragdave.pragprog.com/data/football.dat")


lines   
    |> splitLines   
    |> Seq.skip 5       
    |> Seq.filter (fun (s:string) -> s.Split([|'     '|],StringSplitOptions.RemoveEmptyEntries).Length = 10)    
    |> Seq.map split        
    |> Seq.sortBy balance   
    |> Seq.take 1
    |> Seq.map (fun (n,_,_) -> printfn "%s" n)

What is the difference? List.ofSeq(File.ReadAllLines..) retuns a sequence and downloading the file from the internet and splitting it by \n returns the same sequence


Solution

  • The last line should use Seq.iter instead of Seq.map and there are too many spaces in the expression that splits each line.

    With these corrections it works ok:

    open System.Net
    open System
    open System.IO
    
    let split (s:string) =
        let cells = Array.ofSeq(s.Split([|' '|],StringSplitOptions.RemoveEmptyEntries))    
        (cells.[1], int cells.[6], int cells.[8])
    
    let balance t = 
        let (_,f,a) = t
        -(f-a)
    
    let splitLines (s:string) = 
        List.ofSeq(s.Split([|'\n'|]))
    
    
    let wc = new WebClient()
    let lines = wc.DownloadString("http://pragdave.pragprog.com/data/football.dat") |> splitLines 
    
    let output =
      lines   
        |> Seq.skip 5   
        |> Seq.filter (fun (s:string) -> s.Split([|' '|],StringSplitOptions.RemoveEmptyEntries).Length = 10)    
        |> Seq.map split        
        |> Seq.sortBy balance   
        |> Seq.take 1
        |> Seq.iter (fun (n,_,_) -> Console.Write(n))
    
    let stop = Console.ReadKey()