2015-08-08 1 views
3

Je suis très nouveau à Elm (et je suis nouveau à FP en général) J'ai du mal à comprendre comment faire certaines choses.Elm - analyser le fichier texte en Html

J'utilise les ports actuellement à lire dans un fichier texte et le faire passer à l'orme (index.html):

<script type="text/javascript"> 
    // Show the stamp module in the "elm-div" div. 
    var div = document.getElementById('elm-div'); 
    var golf = Elm.embed(Elm.Golf, div, { reset:[], openFromFile: "" }); 

    var upload = document.getElementById('fileinput'); 

    upload.onchange = function (e) { 
     reader = new FileReader(); 

     reader.onload = function (event) { 
      data = event.target.result; 
      //file's text data is sent to 'openfromfile' port 
      golf.ports.openFromFile.send(data); 
      } 
     reader.readAsText(upload.files[0]); 
     }; 
</script> 

Golf.elm (jusqu'à présent):

module Golf where 

import Html exposing (Html, Attribute, text, toElement, div, input) 
import Html.Attributes exposing (..) 
import Color exposing (..) 
import Signal exposing ((<~),(~)) 
import String 

port reset : Signal() 
port openFromFile : Signal String 

getLines : Signal (List String) 
getLines = String.lines <~ openFromFile 

J'ai du mal à penser à la façon dont le fichier Golf.elm devrait être structuré. J'ai données texte dans un format CSV (délimité par « ») où:

"Round Number", "Par", "steve", "kyle", "rick" 
1, 3, 5, 8, 1 
2, 5, 3, 7, 8 
3, 4, 6, 5, 4 
4, 3, 2, 4, 3 
5, 2, 5, 7, 4 

Ce que je veux faire est de lire le CSV et afficher un tableau HTML avec les scores par rapport à la hauteur pour chaque joueur/tour (score = nombre - par) mais Le fait que je ne commence pas avec un modèle régulier en format d'enregistrement, mais un Signal (List String) m'a complètement perdu.

J'ai envoyé mon getLines à travers les ports de console.log, je sais que je lis correctement le fichier ainsi et générer un Signal (List String) correctement à partir de la source de texte, mais je n'ai pas où aller d'ici.

Répondre

3

Explication

Vous pouvez commencer par types:

type alias CSV = { headers : Maybe (List String) 
       , records : List (List String) 
       } 

Vous avez:

getLines : Signal (List String) 

mais il a besoin:

getCSV : Signal CSV 

Utilisation de base Signal.map:

map : (a -> result) -> Signal a -> Signal result 

Puis tapez la signature sera (a = List String, résultat = CSV):

map0  : (List String -> CSV) -> Signal (List String) -> Signal CSV 

partie manquante est:

parseCSV : List String -> CSV 

Combiner toutes choses:

getCSV : Signal CSV 
getCSV = Signal.map parseCSV getLines 

R esult

-- ... 

getCSV : Signal CSV 
getCSV = Signal.map badParseCSV getLines 

type alias CSV = { headers : Maybe (List String) 
       , records : List (List String) 
       } 

badParseCSV : List String -> CSV 
badParseCSV xs = 
    let parseLine = List.map (trimQuotes << String.trim) 
       << String.split "," 
     trimQuotes x = if String.startsWith "\"" x 
        && String.endsWith "\"" x 
        then String.dropRight 1 <| String.dropLeft 1 x 
        else x 
     records0 = List.map parseLine 
       <| List.filter (\x -> not (String.isEmpty x)) 
       <| List.drop 1 xs 
     headers0 = Maybe.map parseLine <| List.head xs 
    in { headers = headers0 
     , records = records0} 

view : CSV -> Html 
view csv = 
    let rows = List.map (\xs -> Html.tr [] (cols xs)) csv.records 
     cols xs = List.map col xs 
     col x = Html.td [] [ text x] 
     ths xs = List.map (\x -> Html.th [] [text x]) xs 
     headers = Maybe.withDefault [] <| Maybe.map ths csv.headers 
    in Html.table [] [ Html.thead [] headers 
        , Html.tbody [] rows 
        ] 

main : Signal Html 
main = Signal.map view getCSV 
+0

Je suis confus par un certain nombre de choses, tout d'abord je ne suis pas trop familier avec la syntaxe de la composition de fonctions. par exemple dans cette ligne: – leshow

+0

List.map (trimQuotes << String.trim) << String.split "," qu'est-ce que cela équivaut à? Je pensais que ce serait: List.map (trimQuotes (String.trim xs)) (String.split "," xs) mais il semble que ce soit incorrect. Je n'arrive pas à comprendre comment vous avez réussi à prendre le signal (List String) et à laisser tomber la partie signal pour que vous puissiez vous retrouver avec quelque chose de plus utilisable. – leshow

+0

vous pouvez commencer avec 'map (\ x -> f2 (f1 x)) list' équivalent à' map (\ x -> f2 <| f1 x) liste' et pour 'map (\ x -> f1 x |> f2) list' et avec la composition 'map (f2 << f1) list' ou' map (f1 >> f2) list' –