2016-09-04 2 views
1

다른 CSV 파일에서 축구 경기를 읽는 프로그램을 만들고 있습니다. 관심있는 열은 모든 파일에 있지만 파일의 열 수는 다양합니다.F # CsvTypeProvider 약간 다른 CSV 파일에서 동일한 열 추출

type GamesFile14 = CsvProvider<"./data/sample_14.csv"> 
type GamesFile15 = CsvProvider<"./data/sample_15.csv"> 
type GamesFile1617 = CsvProvider<"./data/sample_1617.csv"> 

let mapRows14 (rows:seq<GamesFile14.Row>) = rows |> Seq.map (fun c -> { Division = c.Div; Date = DateTime.Parse c.Date; 
     HomeTeam = { Name = c.HomeTeam; Score = c.FTHG; Shots = c.HS; ShotsOnTarget = c.HST; Corners = c.HC; Fouls = c.HF }; 
     AwayTeam = { Name = c.AwayTeam; Score = c.FTAG; Shots = c.AS; ShotsOnTarget = c.AST; Corners = c.AC; Fouls = c.AF }; 
     Odds = { H = float c.B365H; U = float c.B365D; B = float c.B365A } }) 


let mapRows15 (rows:seq<GamesFile15.Row>) = rows |> Seq.map (fun c -> { Division = c.Div; Date = DateTime.Parse c.Date; 
     HomeTeam = { Name = c.HomeTeam; Score = c.FTHG; Shots = c.HS; ShotsOnTarget = c.HST; Corners = c.HC; Fouls = c.HF }; 
     AwayTeam = { Name = c.AwayTeam; Score = c.FTAG; Shots = c.AS; ShotsOnTarget = c.AST; Corners = c.AC; Fouls = c.AF }; 
     Odds = { H = float c.B365H; U = float c.B365D; B = float c.B365A } }) 


let mapRows1617 (rows:seq<GamesFile1617.Row>) = rows |> Seq.map (fun c -> { Division = c.Div; Date = DateTime.Parse c.Date; 
     HomeTeam = { Name = c.HomeTeam; Score = c.FTHG; Shots = c.HS; ShotsOnTarget = c.HST; Corners = c.HC; Fouls = c.HF }; 
     AwayTeam = { Name = c.AwayTeam; Score = c.FTAG; Shots = c.AS; ShotsOnTarget = c.AST; Corners = c.AC; Fouls = c.AF }; 
     Odds = { H = float c.B365H; U = float c.B365D; B = float c.B365A } }) 

이가 다시 loadGames 기능에 의해 소비되는 :

let loadGames season resource = 
    if season.Year = 14 then GamesFile14.Load(resource).Rows |> mapRows14 
    else if season.Year = 15 then GamesFile15.Load(resource).Rows |> mapRows15 
    else GamesFile1617.Load(resource).Rows |> mapRows1617 

그것을

각 유형에 대해 다른 샘플 파일의 각 변형에 대한 별도의 매핑 함수를 만드는 날 떠났어 이 문제를 해결할 더 좋은 방법이 있어야한다고 생각합니다.

동일한 기능을 반복해서 반복 할 필요가 없도록 매핑 기능을 좀 더 일반화 할 수있는 방법이 있습니까?

리소스를 기반으로 즉석에서 CsvProvider를 만들 수 있습니까? 아니면 위 코드에서와 같이 각 csv 파일 변형에 대한 샘플을 명시 적으로 선언해야합니까?

기타 제안 사항?

답변

2

FSharp.Data's CsvFile type에서 더 좋은 결과를 얻을 수 있습니다. 데이터 액세스에 동적 ? 연산자를 사용하여 CSV 구문 분석에보다 동적 인 접근 방식을 사용합니다. 각 별도의 CSV 파일이 저장 CsvRow 유형에로드되므로 유형 제공자가 제공하는 일부 유형의 안전 보장을 잃게됩니다. 이는 컴파일 타임에 특정 열이 파일에 있음을 보장 할 수 없으며 런타임 오류에 대비해야한다는 것을 의미합니다.

let mapRows14 rows = rows |> Seq.map (fun c -> { Division = c?Div; Date = DateTime.Parse c?Date; 
     HomeTeam = { Name = c?HomeTeam; Score = c?FTHG; Shots = c?HS; ShotsOnTarget = c?HST; Corners = c?HC; Fouls = c?HF }; 
     AwayTeam = { Name = c?AwayTeam; Score = c?FTAG; Shots = c?AS; ShotsOnTarget = c?AST; Corners = c?AC; Fouls = c?AF }; 
     Odds = { H = float c?B365H; U = float c?B365D; B = float c?B365A } }) 

CsvFile 시도를주고이 문제가 해결되는지 확인 : 그것은 당신의 세 가지 기능은 다음과 같이 다시 쓸 수 있습니다 때문에 그러나 귀하의 경우, 즉, 당신이 원하는 단지입니다.