Группировка списка в списки из n элементов в Haskell - программирование
Подтвердить что ты не робот

Группировка списка в списки из n элементов в Haskell

Есть ли операция в списках в библиотеке, которая делает группы из n элементов? Например: n = 3

groupInto 3 [1,2,3,4,5,6,7,8,9] = [[1,2,3],[4,5,6],[7,8,9]]

Если нет, как это сделать?

4b9b3361

Ответ 1

Быстрый поиск по Hoogle показал, что такой функции нет. С другой стороны, ответили, что в пакете split есть один, который называется chunksOf.

Однако вы можете сделать это самостоятельно

group :: Int -> [a] -> [[a]]
group _ [] = []
group n l
  | n > 0 = (take n l) : (group n (drop n l))
  | otherwise = error "Negative n"

Конечно, некоторые круглые скобки можно удалить, я оставил их здесь, чтобы понять, что делает код:

Основной случай прост: всякий раз, когда список пуст, просто возвращайте пустой список.

Сначала рекурсивные тесты, если n положительно. Если n 0 или ниже, мы вводим бесконечный цикл, и мы этого не хотим. Затем мы разбиваем список на две части, используя take и drop: take возвращает первые n элементы, а drop возвращает остальные. Затем мы добавляем первые n элементы в список, полученный путем применения нашей функции к другим элементам в исходном списке.

enter image description here

Ответ 2

Эта функция, среди других аналогичных, может быть найдена в популярном пакете split.

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

Ответ 3

Вы можете написать его сами, как отметил Михай. Но я бы использовал функцию splitAt, так как она не требует двух проходов в списке ввода, например, -drop:

chunks :: Int -> [a] -> [[a]]
chunks _ [] = []
chunks n xs =
    let (ys, zs) = splitAt n xs
    in  ys : chunks n zs

Это общий шаблон - генерирование списка из начального значения (которое в этом случае является вашим списком ввода) с помощью повторной итерации. Этот шаблон фиксируется в функции unfoldr. Мы можем использовать его со слегка измененной версией splitAt (спасибо Will Ness для более сжатой версии):

chunks n = takeWhile (not.null) . unfoldr (Just . splitAt n)

То есть мы генерируем фрагменты из n элементов, в то же время мы сокращаем входной список на n, используя unfoldr, и мы генерируем эти куски, пока не получим пустой список - в этот момент исходный вход полностью потребляется.

Конечно, как указывали другие, вы должны использовать уже существующую функцию из разделенного модуля. Но всегда полезно приучать себя к функциям обработки списков в стандартных библиотеках Haskell.

Ответ 4

Это свойство называется "chunk" и является одним из наиболее часто упоминаемых операций с списком, не находящимся в base. Пакет split предоставляет такую ​​операцию, хотя копирует и вставляет документацию на пикши:

 > chunksOf 3 ['a'..'z']
 ["abc","def","ghi","jkl","mno","pqr","stu","vwx","yz"]

Кроме того, в отличие от моих пожеланий, hoogle ищет только небольшой набор библиотек (те, которые поставляются с GHC или, возможно, HP), но вы можете явно добавлять пакеты к поиску с помощью +PKG_NAME - hoogle с Int -> [a] -> [[a]] +split получает то, что вы хотите, Некоторые люди используют Hayoo по этой причине.