简体   繁体   English

使用 fold in haskell 将列表转换为列表列表

[英]Transform a list into a list of lists with fold in haskell

I have this code:我有这个代码:

fromList :: Int -> [Int] -> [[Int]]
fromList y = takeWhile (not.null) . map (take y) . iterate (drop y) 

An example of what this does: -> fromList 4 [1..19]这样做的一个例子: -> fromList 4 [1..19]

[[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16],[17,18,19]]

How can I make this code using a fold?如何使用折叠制作此代码?

Here's a pretty elegant solution using foldr :这是一个使用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]]
    ) []

Essentially, the accumulator is the end value, and for each value in the list it checks if there's still space to put it in an existing chunk, and if there isn't then it puts it in a new chunk.本质上,累加器是最终值,对于列表中的每个值,它检查是否还有空间将其放入现有块中,如果没有,则将其放入新块中。 Sadly, due to using foldr , extra elements are put on the left side instead of the right side.可悲的是,由于使用foldr ,额外的元素放在左侧而不是右侧。 This can be fixed by using a slightly slower (and maybe slightly uglier) approach with foldl (or foldl' ):这可以通过对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

Here's one way.这是一种方法。

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,2,3],[4,5,6],[7,8,9],[10,11,12]]

-- > take 3 . map (take 2) . foo 3 $ [1..8] ++ undefined
-- => [[1,2],[4,5],[7,8]]

It creates the output as you have described it, and does so in a lazy enough way so that it works with infinite lists as well.它按照您的描述创建输出,并且以一种足够懒惰的方式执行此操作,因此它也可以与无限列表一起使用。

( edit: made it even lazier so that the last example would work, based off the idea by Daniel Fischer ) 编辑:根据Daniel Fischer的想法,让它变得更加懒惰,以便最后一个示例可以工作)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM