List 分段Haskell列表
给定haskell中的一个排序列表,如何获得连续数字放在同一个列表中的分段列表。例如,如果我有一个排序列表List 分段Haskell列表,list,haskell,List,Haskell,给定haskell中的一个排序列表,如何获得连续数字放在同一个列表中的分段列表。例如,如果我有一个排序列表[1,2,3,4,7,8,10,12,13,15],结果将是[[1,2,3,4],[7,8],[10],[12,13],[15],此函数可以提供帮助 addFirstInRun::Int->[Int]->[(Int, Int)] addFirstInRun _ [] = [] addFirstInRun lowVal (x:y:rest) | y - x > 1 = (lo
[1,2,3,4,7,8,10,12,13,15]
,结果将是[[1,2,3,4],[7,8],[10],[12,13],[15]
,此函数可以提供帮助
addFirstInRun::Int->[Int]->[(Int, Int)]
addFirstInRun _ [] = []
addFirstInRun lowVal (x:y:rest) | y - x > 1 = (lowVal, x):firstInRun y (y:rest)
addFirstInRun lowVal (x:rest) = (lowVal, x):firstInRun lowVal rest
它将列表中的每个值与另一个数字(当前箱子的“头”)配对
> addFirstInRun 1 [1,2,3,5,6,7,10]
[(1,1),(1,2),(1,3),(5,5),(5,6),(5,7),(10,10)]
(很抱歉,您需要手动放入第一个……您可以编写一个方便的包装来修复此问题)
使用此选项,您可以使用groupBy
groupBy ((==) `on` fst)
你可以用这个来清理最后的答案
map (map snd)
把这些放在一起
> map (map snd) $ groupBy ((==) `on` fst) $ addFirstInRun 1 [1,2,3,5,6,7,10]
[[1,2,3],[5,6,7],[10]]
(您需要导入
数据.Function
和数据.List
)解决方案的概要:
1-将每个元素与下一个元素配对:
(1,2) (2,3) (3,4) (4,7) (7,8) (8,10) (10,12) (12,13) (13,15) ...
2-检查每对是否连续:
(1,2) (2,3) (3,4) (4,7) (7,8) (8,10) (10,12) (12,13) (13,15) ...
True True True False True False False True False ...
3-在False
值处分解列表:
(1,2) (2,3) (3,4) (4,7) | (7,8) (8,10) | (10,12) | (12,13) (13,15) | ...
True True True False | True False | False | True False | ...
4-对于每个段,取成对的fst
:
1 2 3 4 | 7 8 | 10 | 12 13
这只是一个折页:
q :: (Enum a, Eq a) => [a] -> [[a]]
q = foldr foo []
where
foo x (ys@(y:_) : zzs) | succ x == y = (x:ys) : zzs
foo x t = [x] : t
*Main>q[1,2,3,4,7,8,10,12,13,15]
[1,2,3,4]、[7,8]、[10]、[12,13]、[15]]
更新:也可以将其转换为foldl,在这里我使用“差异列表”来实现:
type N a = Maybe ( [[a]] -> [[a]], [a] -> [a], a )
p :: (Enum a, Eq a) => [a] -> [[a]]
p = close . foldl bar Nothing
where
close :: N a -> [[a]]
close Nothing = []
close (Just (f, g, _)) = (f . (g []:)) []
bar :: (Enum a, Eq a) => N a -> a -> N a
bar Nothing x = Just (id, (x:), x)
bar (Just (f, g, y)) x | succ y == x = Just (f, g . (x:), x)
| otherwise = Just ( f . (g []:), (x:), x)
更新2:“f”是一个在无限列表上安全的变体:
f :: (Enum a, Eq a) => [a] -> [[a]]
f [] = []
f (x:xs) = go x xs
where
go x xs = let (run, rest) = getRun x xs
in run : f rest
getRun x t@(y:ys) | succ x == y = let (run, rest) = getRun y ys
in (x:run, rest)
getRun x t = (x:[], t)
或较短的“f”:
f :: (Enum a, Eq a) => [a] -> [[a]]
f [] = []
f (x:xs) = getRun x xs
where
getRun x t@(y:ys) | succ x == y = let (run : rest) = getRun y ys
in (x:run) : rest
getRun x t = (x:[]) : f t
t3 = [1,2,3,10,11,12] ++ [15..]
*干道>第三道(地图(第五道)(t3层))
[1,2,3]、[10,11,12]、[15,16,17,18,19]]
也许你可以让
groupBy
做一些有用的事情?是的,但不太确定如何使用它。我试过groupBy(\x y->x-y==1)[1,2,3,4,7,8,10,12,13,15]它给了我错误!尝试导入数据。列出你的groupBy表达式错误是x和y不在范围内。无论如何,groupBy在这种情况下不起作用,它根据连续元素测试组中的第一个元素,而不是根据下一个元素测试最后一个匹配。e、 g.它将测试(1,2)、(1,3)
而不是(1,2)、(2,3)
。