如何解决将列表转换为在haskell中具有折叠的列表的列表
我有此代码:
fromList :: Int -> [Int] -> [[Int]]
fromList y = takeWhile (not.null) . map (take y) . iterate (drop y)
此功能的示例:
-> fromList 4 [1..19]
[[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16],[17,18,19]]
如何折叠显示代码?
解决方法
这是使用foldr
的非常优雅的解决方案:
fromList :: Int -> [a] -> [[a]]
fromList n = foldr (\v a ->
case a of
(x:xs) -> if length x < n then (v:x):xs else [v]:a
_ -> [[v]]
) []
本质上,累加器是最终值,对于列表中的每个值,它都会检查是否还有空间将其放入现有块中,如果没有,则将其放入新块中。可悲的是,由于使用foldr
,多余的元素被放置在左侧而不是右侧。可以通过在foldl
(或foldl'
)中使用稍微慢一些(也许更丑陋)的方法来解决此问题:
fromList :: Int -> [a] -> [[a]]
fromList _ [] = []
fromList n (x:xs) = reverse $ foldl (\a@(y:ys) v ->
if length y < n
then (y ++ [v]):ys
else [v]:a
) [[x]] xs
,
这是一种方法。
foo :: Int -> [t] -> [[t]]
foo k xs | k > 0 = foldr cons [] .
zip xs . cycle $ (False <$ [2..k]) ++ [True]
where
cons (a,True) ys = [a] : ys
cons (a,False) ys = (a:x) : zs
where
(x,zs) | null ys = ([],[])
| otherwise = (head ys,tail ys)
-- > foo 3 [1..10]
-- => [[1,2,3],[4,5,6],[7,8,9],[10]]
-- > take 4 . foo 3 $ [1..]
-- => [[1,[10,11,12]]
-- > take 3 . map (take 2) . foo 3 $ [1..8] ++ undefined
-- => [[1,2],5],8]]
它会按照您所描述的那样创建输出,并且以足够懒惰的方式进行,因此它也可以与无限列表一起使用。
( edit:变得更加懒惰,因此根据the idea和Daniel Fischer),最后一个示例可以正常工作
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。