2016-05-29 5 views
2

ich einige Daten in txt-Datei haben, die wie folgt aussieht:Haskell: int Liste von Listen aus einem einzelnen String machen

[Just 3, Nothing, Just 1, Nothing] [Nothing, Nothing, Nothing, Nothing] [Nothing, Nothing, Just 4, Nothing] [Nothing, Just 3, Nothing, Nothing] 

Was ich brauche, ist die Liste der Listen obigen Werte als ganze Zahlen enthalten haben z.B

[[3,0,1,0],[0,0,0,0],....] 

Und so weiter. Hast du eine Idee, wie es richtig gemacht wird? Ich kann "nothing" durch 0 ersetzen und "Just" part löschen, aber es bleibt als einzelne Saite.

Antwort

1

Der richtige Weg, dies zu tun, ist wahrscheinlich eine Parser-Bibliothek wie Text.Parsec zu verwenden. Davon abgesehen, hier ist ein schneller und hacky Weg, um es zu tun, nicht anders als was ein Python-Programmierer mit sich bringen könnte. Die Idee ist, die Eingabe-Zeichenfolge in ein Formular zu massieren, das read für uns analysieren wird.

{-# LANGUAGE OverloadedStrings #-} 

import Prelude hiding (null) 
import Data.Text (snoc, pack, unpack, splitOn, strip, null) 
import Data.Maybe (fromMaybe) 
import System.IO 

parse :: String -> [[Maybe Int]] 
parse = map read . map unpack . map (flip snoc ']') . filter (not . null) . map strip . splitOn "]" . pack 

main :: IO() 
main = do 
    input <- readFile "myfile.txt" -- input = "[Just 3, Nothing, Just 1, Nothing] [Nothing, Nothing, Nothing, Nothing] [Nothing, Nothing, Just 4, Nothing] [Nothing, Just 3, Nothing, Nothing]" 
    putStrLn . show $ map (map (fromMaybe 0)) (parse input) 

Die parse Methode funktioniert wie folgt:

  • pack wandelt einen String Wert in einen Text Wert
  • splitOn "]" tut genau das, was Sie denken
  • map strip entfernt führende und nachfolgende Leerzeichen
  • filter (not . null) entfernt emp ty strings (es gibt eine am Ende)
  • map (flip snoc ']') den „]“ Charakter zurück zum Ende jeden
  • Zeichenfolge append
  • map unpack wandelt jeden Text Wert wieder auf einen String Wert
  • map read parst jeden String Wert in ein [Maybe Int]
+0

Sie definieren Eingabe als eine Liste von String-Listen. In meinem Fall bekomme ich eine einzelne Zeichenfolge aus der Datei und das ist das Hauptproblem. – Dominik

+0

Ah. Aha. Ich werde meine Antwort anpassen. – user2297560

+0

Das ist beeindruckend, aber es sieht so aus, als würde ich immer noch den IO-Typ (oder String) bekommen und was ich brauchte, war [[int]] – Dominik

0

Nur eine alternative Version, die read verwendet:

import Data.List.Split (splitOn) 
import Data.Maybe  (fromMaybe) 

main :: IO() 
main = do 
    s <- readFile "lists.txt" 
    let xs = map (\s' -> map (fromMaybe 0) (read (s' ++ "]"))) . init . splitOn "]" $ s 
    print xs 

Die Idee ist einfach: zuerst wird der Dateiinhalt als String gelesen und an s gebunden. Dann wird s zu einer Liste von Ganzzahlen geparst ([Int]), die an xs gebunden ist. Damit sind, dass die folgenden Schritte tun wurde:

  1. splitOn "]": Teilt die Eingabezeichenfolge s eine Liste von Zeichenketten ([String]) zu erzeugen. Jedes Element verfehlt das Zeichen am Ende. Das letzte Element dieser Liste ist ein unerwünschter "\n". Die resultierende Liste ist:

    ["[Just 3, Nothing, Just 1, Nothing"," [Nothing, Nothing, Nothing, Nothing", ..., "\n"] 
    
  2. init: entfernt die unerwünschten "\ n".

  3. map (\s' -> map (fromMaybe 0) (read (s' ++ "]"))): gilt für jede Saite Element der umschlossene Lambda-Funktion, die bewirkt:

    1. read (s' ++ "]"): Die verschwundenen ']' auf die Zeichenfolge angehängt und parst sie zu einer Liste von Maybe s (Num a => [Maybe a]). Beachten Sie, dass wir keinen Typ explizit für read angeben müssen, weil GHC aus der Verwendung von fromMaybe 0 (siehe unten) schließen kann.
    2. map (fromMaybe 0): wenden Sie die Funktion fromMaybe 0 auf jedes Element der Liste an, die v zurückgibt, wenn Just v; und 0, sonst.

Auf diese Weise können Sie eine Liste von Integer-Listen erhalten read verwenden.

Verwandte Themen