Elm - parsovanie zoznamu zanorených položiek

beginner

Elm - parsovanie zoznamu zanorených položiek
« kdy: 02. 04. 2017, 16:02:20 »
Mám takýto retazec:

Kód: [Vybrat]
- polozka1
    - polozka2
        - polozka3
    - polozka4

a potreboval by som z neho urobiť strom zanorených položiek takéhoto typu
Kód: [Vybrat]
type Node = Node { text : String, children : List Node }
zanorené podľa počtu tabulátorov.

Kód: [Vybrat]
import String
import List

strReplace : String -> String -> String -> String
strReplace oldValue newValue input =
    input
    |> String.split oldValue
    |> String.join newValue

strReplaceAll : List (String, String) -> String -> String
strReplaceAll replacements input =
    case replacements of
    [] -> input
    (oldValue, newValue) :: replacements ->
        strReplaceAll replacements (input |> strReplace oldValue newValue)

unifyEols : String -> String
unifyEols =
    strReplaceAll
    [
        ("\r\n", "\n"),
        ("\n\r", "\n"),
        ("\r", "\n")
    ] >> \str ->
        if str |> String.endsWith "\n"
        then str
        else str ++ "\n"

toIdentList : String -> List (Int, String)
toIdentList input =

    let asString = List.reverse >> String.fromList >> String.trim in
   
    let parseIdent count input =
        case input of
        '\t' :: t -> t |> parseIdent (count + 1)
        data -> (count, data) in

    let parseLine acc input =
        case input of
        '\n' :: t -> (acc, t)
        h :: t -> t |> parseLine (h :: acc)
        [] -> (acc, []) in

    let parse acc input =
        case input of
        [] -> acc
        data ->
            let (ident, tail1) = data |> parseIdent 0 in
            let (chars, tail2) = tail1 |> parseLine [] in
            tail2 |> parse ((ident, chars |> asString) :: acc) in
    input
    |> unifyEols
    |> String.toList
    |> parse []
    |> List.reverse

zatiaľ mám hotovú funkciu toIdentList ktorá mi vracia zoznam položiek a ich zanorenie teda na výstupe dostanem:

Kód: [Vybrat]
[(0, "- polozka1"), (1, "- polozka2"), (2, "- polozka3"), (1, "- polozka4")]

ako to previesť na strom položiek?


BoneFlute

  • *****
  • 1 981
    • Zobrazit profil
Re:Elm - parsovanie zoznamu zanorených položiek
« Odpověď #1 kdy: 03. 04. 2017, 23:17:02 »
Chytil bych se té hodnoty zanoření.

Pokud je roven, generuju sourozence.
Pokud je větší zavolám rekursivně sebe sama a předám mu tail (ocásek zatím nepřežvejkaných prvků).
Pokud je menší, vrací strom vytvořených prvků, a zbytek ocásku.

Funkce dostane jako parametr seznam těch naparsovaných prvků a vrací vytvořený podstrom, a zbytek nezpracovaných prvků.

Boo

Re:Elm - parsovanie zoznamu zanorených položiek
« Odpověď #2 kdy: 04. 04. 2017, 09:55:21 »
Stromy = rekurze. V tvem pripade bych rovnou sel do vyvazeneho stromu pro pripadne dalsi operace. Muzes si taky zjednodusit zivot pouzitim hotove knihovny http://package.elm-lang.org/packages/zwilias/elm-tree/1.0.0/Tree-AVL

gll

Re:Elm - parsovanie zoznamu zanorených položiek
« Odpověď #3 kdy: 04. 04. 2017, 10:49:10 »
Stromy = rekurze. V tvem pripade bych rovnou sel do vyvazeneho stromu pro pripadne dalsi operace. Muzes si taky zjednodusit zivot pouzitim hotove knihovny http://package.elm-lang.org/packages/zwilias/elm-tree/1.0.0/Tree-AVL

to je blbost. AVL je binární strom sloužící k reprezentaci množin. On potřebuje obecný strom k reprezentaci té jeho struktury.

andy

Re:Elm - parsovanie zoznamu zanorených položiek
« Odpověď #4 kdy: 04. 04. 2017, 11:05:02 »
Tohle funguje v Haskellu, předpokládám, že do Elmu to půjde převést poměrně snadno (odstranil jsem haskelloviny..). Moc jsem to netestoval....

Kód: [Vybrat]
input :: [(Int, String)]
input = [(0, "- polozka1"), (1, "- polozka2"), (2, "- polozka3"), (1, "- polozka4")]

data Node = Node {
    text :: String,
    children :: [Node]
} deriving (Show)

genTree :: [(Int, String)] -> [Node]
genTree =  map snd . foldr merge [] . map (\(lvl,txt) -> (lvl, Node txt []))
  where
    merge (l, left) [] = [(l, left)]
    merge (l, left) acc@((r,_):_)
      | l >= r = (l,left):acc
      | otherwise =
          let (childs,siblings) = span (\(lvl,_) -> lvl > l) acc
          in (l, Node (text left) (map snd childs)) : siblings