Подтвердить что ты не робот

Разделение списка в haskell

Как я могу сгруппировать список в более мелкие списки равной длины (кроме последнего подсписок) в haskell?

например.

sublist 3 [1,2,3,4,5,6,7,8] -> [[1,2,3],[4,5,6],[7,8]]
sublist 2 [4,1,6,1,7,3,5,3] -> [[4,1],[6,1],[7,3],[5,3]]
4b9b3361

Ответ 1

Если вы хотите придерживаться прелюдии, вы можете отключить ее, используя splitAt.

splitEvery _ [] = []
splitEvery n list = first : (splitEvery n rest)
  where
    (first,rest) = splitAt n list

Ответ 2

Try:

import Data.List.Split
> splitEvery 2 [4,1,6,1,7,3,5,3]
[[4,1],[6,1],[7,3],[5,3]]

Ответ 3

Модуль Data.List.Split имеет функцию chunksOf для этого:

Prelude> import Data.List.Split

Prelude Data.List.Split> chunksOf 3 [1,2,3,4,5,6,7,8,9,10]
[[1,2,3],[4,5,6],[7,8,9],[10]]
Prelude Data.List.Split> chunksOf 3 []
[]

Кажется, он был установлен по умолчанию на моей машине, но вам может потребоваться его с помощью cabal.

Ответ 4

Другим решением, которое мне нравится, является:

splitEvery :: Int -> [a] -> [[a]]
splitEvery n = takeWhile (not.null) . map (take n) . iterate (drop n)

Ответ 5

Еще одно решение:

split :: Int -> [a] -> [[a]]
split n = unfoldr (\s -> if null s then Nothing else Just $ splitAt n s)

Ответ 6

Я знаю, что это старо, но, поскольку это, похоже, является почтой для людей, которые довольно новы для Haskell, мне также хотелось опубликовать мое решение. Я попытался решить эту проблему, используя Prelude, только:

sublist :: Int -> [a] -> [[a]]
sublist n ls
    | n <= 0 || null ls = []
    | otherwise = take n ls:sublist n (drop n ls)

Тестирование

sublist 3 [1,2,3,4,5,6] -- λ> [[1,2,3], [4,5,6]]
sublist 5 [1,2,3]       -- λ> [[1,2,3]]
sublist (-1) [1,2,3]    -- λ> []
sublist 20 []           -- λ> []