Haskell: создать кортеж списков из списка ввода - PullRequest
2 голосов
/ 14 марта 2020

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

У меня есть список [a], и я хочу, чтобы он выводил кортеж из четырех разных списков ([b],[b],[b],[b]), где каждый элемент в списке [a] последовательно помещается в следующий список в выходном кортеже. Таким образом, первый элемент в списке ввода [a] переходит в первый список [b], второй элемент в [a] переходит во второй список [b], третий элемент в [a] переходит в третий список [b], и так далее. Я пытался использовать chunksOf и splitEvery / splitAt, но не могу получить правильный вывод. И помощь будет принята с благодарностью! Спасибо!

Ответы [ 2 ]

7 голосов
/ 14 марта 2020

Вы каждый раз " вращаете " 4-кортеж и переходите к первому элементу. Таким образом, мы можем реализовать это с помощью шаблона foldr, который выглядит следующим образом:

toFour :: [a] -> ([a], [a], [a], [a])
toFour = foldr (<b>\a (bs, cs, ds, as) -> (a:as, bs, cs, ds)</b>) ([], [], [], [])

или с неопровержимым шаблоном:

toFour :: [a] -> ([a], [a], [a], [a])
toFour = foldr (\a <b>~(bs, cs, ds, as)</b> -> (a:as, bs, cs, ds)) ([], [], [], [])

Так что здесь (bs, cs, ds, as) - это 4-кортеж, который мы сгенерировали для хвоста списка и «вращаем» вправо, чтобы создать кортеж (as, bs, cs, ds), а затем добавляем элемент a к первому списку из четырех кортежей.

Для список целых чисел, это дает нам:

Prelude> toFour [1..2]
([1],[2],[],[])
Prelude> toFour [1..3]
([1],[2],[3],[])
Prelude> toFour [1..4]
([1],[2],[3],[4])
Prelude> toFour [1..5]
([1,5],[2],[3],[4])
Prelude> toFour [1..6]
([1,5],[2,6],[3],[4])
Prelude> toFour [1..10]
([1,5,9],[2,6,10],[3,7],[4,8])

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

Prelude> (\(_, l, _, _) -> take 10 l) (toFour [1..])
[2,6,10,14,18,22,26,30,34,38]
4 голосов
/ 14 марта 2020

Определить

f n = transpose . chunksOf n
g xs = let [xs1, xs2, xs3, xs4] = f 4 xs in (xs1, xs2, xs3, xs4) 

Где f - общее решение. Это дает

Prelude> g ['a' .. 'z']
("aeimquy","bfjnrvz","cgkosw","dhlptx") 

Подписи

Prelude> :t g
g :: [a] -> ([a], [a], [a], [a])

и

Prelude> :t f
f :: Int -> [a] -> [[a]]

Информация о:

...