如何在Haskell中实现一种在命令式语言中简单易行的转换,因为它可以轻松更新地图及其内容?
while( line = next()) {
Data d = parse(line);
if( map.get(d.key) == null) map.put(d.info);
else map.get(d.key).update(d.info);
}
for(d : map.values) print d.computeResult()
为了给出(过度简化的)具体示例,输入将包含需要通过某些规则进行关联的行。在这里,程序应检测到键'k'下的值被添加,更新但最终被删除,不应出现在输出中。
[time] ADD key=k, value1=V1
[time] ADD key=k, value2=V2
[time] ADD key=k, value1=ABC
[time] [...]
[time] DEL key=k
[time] ADD key=k2, value1=V1
我应该考虑使用镜头,状态monad,按键(如果可能)或其他东西对数据进行排序?哪个是最干净的方式(至少用boilerplatte)来实现这个?我想知道这样的Haskell脚本是否比awk / sed / grep / xmlstartlet汤更容易维护。
答案 0 :(得分:5)
insert :: Ord k => k -> a -> Map k a -> Map k a
的 Data.Map
完全符合您的要求。
import qualified Data.Map as M
addLines :: [String] -> M.Map Int String
addLines = foldr (uncurry M.insert) M.empty . parseLines
where parseLines :: [String] -> [(Int, String)]
parseLines = zip [1..]
addLines
获取要存储的行列表,返回Map
,行号作为行的键。如果您只是将一大堆文字投入String
,请使用lines :: String -> [String]
将其分成几行。
正如Gabriel在评论中所建议的,将一系列行转换为Map
的更好方法是
addLines = M.fromList . zip [1..]
注意:第一个函数允许您传入初始Map
而不是M.empty
,但使用M.union
将Map
与第二个函数组合可能会更快。