给定一系列元素,我想找到每个元素的所有直接后继的列表:
示例:
"AABAABAAC"
应返回类似(使用Data.Map
)的内容:
fromList [('A',"ABABA"), ('B',"AA"), ('C', "")]
我知道fromListWith
函数,但我似乎无法使列表理解正确:
succs :: Ord a => [a] -> M.Map a [a]
succs xs = M.fromListWith (++) [(x, ???) | ??? ]
答案 0 :(得分:3)
这有帮助吗?
succs xs@(_:xss) = M.fromListWith (++) $ zip xs (map (:[]) xss ++ [[]])
我认为它返回('A',"ABABAC")...
,您的示例没有C
。
(:[])
是
singleton :: a -> [a]
singleton x = [x]
我是如何得到这个解决方案的?我发现斐波那契数字的这个定义令人着迷:[1] [2]
fibs = fibs = 0:1:zipWith (+) fibs (tail fibs)
类似的事情可以将每个元素与其后继者配对:
let x = "AABAABAAC"
zip x (tail x)
[('A','A'),('A','B'),('B','A'),('A','A'),('A','B'),('B','A'),('A','A'),('A','C')]
此类型几乎匹配
的输入M.fromListWith :: Ord k => (a -> a -> a) -> [(k, a)] -> M.Map k a
现在将字符转换为单个列表并添加一个空列表以禁止('C',"")
。
答案 1 :(得分:1)
您可以将问题分成两部分。首先,找到列表中两个元素之间的边缘。
edges :: [a] -> [(a, a)]
edges (x:y:zs) = (x,y):edges (y:zs)
edges _ = []
然后使用fromListWith
为所有项目的直接后继者构建地图。
succs :: Ord a => [a] -> M.Map a [a]
succs = M.fromListWith (++) . map (\(x,y) -> (x,[y])) . edges
这并不能完全满足您的需求。 'C'
没有条目,因为它没有立即接班人。
succs "AABAABAAC" = fromList [('A',"CABABA"),('B',"AA")]
相反,我们可以制作一个不太通用的edges
版本,其中包含列表中最后一项的项目。
succs :: Ord a => [a] -> M.Map a [a]
succs = M.fromListWith (++) . edges
where
edges (x:y:zs) = (x,[y]):edges (y:zs)
edges (x:zs) = (x,[] ):edges zs
edges _ = []