/ / Analyzovať reťazce, ktoré sú obklopené úvodzovkami - json, string, haskell

Rozdeľte reťazce, ktoré sú obklopené citátmi - json, string, haskell

Analyzujem niektoré údaje, ktoré nekontrolujem. Mám hodnoty, ktoré sú radom reťazcov. Môže to byť buď normálny reťazec, reťazcové znázornenie čísla alebo číslo s úvodzovkami.

["This is just a string", ""5"", "3"]

Chcel by som napísať funkciu toValue ktorý ich prevádza na vhodný typ, ktorý sa má previesť na JSON.

toValue :: (ToJSON a) => String -> a
toValue (if a number) = parseInt
toValue (if a quoted number) = parseInt . stripQuotes
toValue _ = id

Chcel by som odškrtnúť úvodzovky, ak je to číslo obklopené úvodzovkami, potom ich skonvertovať na číslo, ak číslo, inak ho odovzdať späť ako reťazec.

Môžem to urobiť so zhodou vzorov? Iným spôsobom?

odpovede:

3 pre odpoveď č. 1
    import Data.Char
import Data.Bool

parse a@(""":n:""":[]) = bool (Left a) (Right (read [n] :: Int)) (isNumber n)
parse a@(""":n:m:""":[]) = bool (Left a) (Right (read [n,n] :: Int)) (isNumber n && isNumber m)
parse a@(n:[]) = bool (Left a) (Right (read [n] :: Int)) (isNumber n)
parse a@(n:m:[]) = bool (Left a) (Right (read [n,n] :: Int)) (isNumber n && isNumber m)
parse xs = Left xs

> map parse ["This is just a string", ""5"", "3"]
[Left "This is just a string",Right 5,Right 3]

potom môžete použiť either funkcia od Data.Either modul na kódovanie čísla (Práva) a reťazca (Lefts) do JSON.


-1 pre odpoveď č. 2

Písanie funkcie toValue :: ToJSON a => String -> a ako navrhujete, nie je také ťažké: jednoducho urobme to toValue metóda triedy ToJSON

class ToJSON a where
toValue :: String -> a

a potom definujte inštanciu pre Int ako

instance ToJSON Int where
toValue s@(""" : _) = read (read s) -- with quotes
toValue s            = read s        -- without quotes

Príklad pre String je trochu viac zapojený (ako String je synonymom pre [Char]), ale v žiadnom prípade raketová veda:

class ToJSONList a where
toValues :: String -> [a]

instance ToJSONList Char where
toValues = id

instance ToJSONList a => ToJSON [a] where
toValue = toValues

Teraz, pri testovaní v interaktívnej relácii, máme:

> toValue "This is just a string" :: String
"This is just a string"

> toValue ""5"" :: Int
5

> toValue "3" :: Int
3

Z vašej otázky sa však zdá, že máte prípad použitia, ktorý nie je takouto funkciou dostatočne podporený toValue, t. j. na konverziu všetkých prvkov zoznamu na príslušné zastúpenie JSON. Pravdepodobne budete chcieť zaviesť algebraický dátový typ reprezentujúci hodnoty JSON:

data JSON = JInt Int | JString String deriving Show

a potom fungujú voči spoločnosti JSON, ktorá riadi ich najvhodnejšie zastúpenie JSON:

toJSON :: String -> JSON
toJSON    s      =
case reads s of
[(n, "")] -> JInt n                                   -- Int, no quotes
_         -> case reads s of
[(s, "")] -> case reads s of
[(n, "")] -> JInt n     -- Int, quotes
_         -> JString s  -- String, quotes
_         -> JString s                 -- String, no quotes

Na zodpovedanie tejto časti otázky je potrebné odpovedať:táto funkcia je definovaná iba (vnoreným) porovnaním vzorov. Ak sa však (gramatika) jazyka, ktorý musíte analyzovať, stáva zložitejším, potom iba celočíselnými literálmi, citovanými celočíselnými literármi a reťazcovými literálmi, tento spôsob definovania analyzátorov sa rýchlo stáva neohrabanou a náchylnou na chyby a možno budete chcieť začať pozerať sa do kombinátory syntaktického analyzátora alebo generátory syntaktického analyzátora potom.

Pre váš jednoduchý jazyk hodnôt JSON je to však stále v poriadku. Tu je jednoduchý príklad interaktívnej relácie:

> map toJSON ["This is just a string", ""5"", "3"]
[JString "This is just a string",JInt 5,JInt 3]