Iul*_*anu 2 haskell parentheses
假设我有一个字符串,如:
abc(def(gh)il(mn(01))afg)lmno(sdfg*)
Run Code Online (Sandbox Code Playgroud)
如何确定第一个的匹配括号?(意思(def(gh)il(mn(01))afg))
我试图通过计算开放括号的数量直到第一个')'来创建一个between函数,但它不适用于像这样的字符串.
您可以使用一个简单地遍历字符串的函数,同时跟踪一组开括号的索引.每当遇到右括号时,您就会知道它与堆栈顶部的索引匹配.
例如:
parenPairs :: String -> [(Int, Int)]
parenPairs = go 0 []
where
go _ _ [] = []
go j acc ('(' : cs) = go (j + 1) (j : acc) cs
go j [] (')' : cs) = go (j + 1) [] cs -- unbalanced parentheses!
go j (i : is) (')' : cs) = (i, j) : go (j + 1) is cs
go j acc (c : cs) = go (j + 1) acc cs
Run Code Online (Sandbox Code Playgroud)
此函数返回属于匹配括号对的所有索引对的列表.
将该函数应用于示例字符串会给出:
> parenPairs "abc(def(gh)il(mn(01))afg)lmno(sdfg*)"
[(7,10),(16,19),(13,20),(3,24),(29,35)]
Run Code Online (Sandbox Code Playgroud)
您感兴趣的左括号出现在索引3处.返回的列表显示匹配的右括号将在索引24处找到.
以下函数为您提供字符串的所有正确括号段:
parenSegs :: String -> [String]
parenSegs s = map (f s) (parenPairs s)
where
f s (i, j) = take (j - i + 1) (drop i s)
Run Code Online (Sandbox Code Playgroud)
例如:
> parenSegs "abc(def(gh)il(mn(01))afg)lmno(sdfg*)"
["(gh)","(01)","(mn(01))","(def(gh)il(mn(01))afg)","(sdfg*)"]
Run Code Online (Sandbox Code Playgroud)
根据Frerich Raabe的建议,我们现在也可以编写一个只返回最左边段的函数:
firstParenSeg :: String -> String
firstParenSeg s = f s (minimum (parenPairs s))
where
f s (i, j) = take (j - i + 1) (drop i s)
Run Code Online (Sandbox Code Playgroud)
例如:
> firstParenSeg "abc(def(gh)il(mn(01))afg)lmno(sdfg*)"
"(def(gh)il(mn(01))afg)"
Run Code Online (Sandbox Code Playgroud)
请注意,firstParenSeg如果输入字符串不包含至少一对匹配的括号,则会失败.
最后,对parenPairs函数的一个小修改使它在不平衡的括号上失败:
parenPairs' :: String -> [(Int, Int)]
parenPairs' = go 0 []
where
go _ [] [] = []
go _ (_ : _ ) [] = error "unbalanced parentheses!"
go j acc ('(' : cs) = go (j + 1) (j : acc) cs
go j [] (')' : cs) = error "unbalanced parentheses!"
go j (i : is) (')' : cs) = (i, j) : go (j + 1) is cs
go j acc (c : cs) = go (j + 1) acc cs
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1159 次 |
| 最近记录: |