Haskell - чередующиеся элементы из двух списков - PullRequest
12 голосов
/ 12 декабря 2011

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

У меня есть функция:

blend xs ys

Пример:

blend [1,2,3] [4,5,6]

должен вернуть

[1,4,2,5,3,6]

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

Это удаляет их из их кортежей, которые я не могу понять, как реализовать.

Ответы [ 4 ]

19 голосов
/ 12 декабря 2011

Как насчет обмена аргументами во время рекурсии-спуска?

blend (x:xs) ys = x:(blend ys xs)
blend _ _ = []

Вы можете даже обобщить этот подход для любого числа списков (я оставлю это вам) или взять оставшиеся элементы списка, если другой пуст:

blend _ ys = ys
6 голосов
/ 12 декабря 2011

Я буду считать, что это домашнее задание. При условии, что вы можете создать следующий список (как вы сказали):

[(1,4),(2,5),(3,6)]

... вы можете решить это с 2 функциями:

  1. Вам необходимо преобразовать кортеж (a, b) в список [a, b]. Попробуйте использовать сопоставление с шаблоном! Эту функцию необходимо применить (она же отображена) ко всем имеющимся элементам списка.
  2. У вас будет список списков, например [[1,4],[2,5],[3,6]], поэтому вам нужна функция для объединения подсписков в один большой список.

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

5 голосов
/ 12 декабря 2011

Если вы хотите архивировать, генерируйте списки вместо кортежей:

concat $ zipWith (\x y -> [x,y]) [1,2,3] [4,5,6]

Немного бессмысленного веселья:

concat $ zipWith ((flip(:)).(:[])) [1,2,3] [4,5,6]  

Наверное, самый простой способ:

import Data.List
concat $ transpose [[1,2,3],[4,5,6]]
2 голосов
/ 12 декабря 2011

Решение без использования concat или явной рекурсии:

blend l = foldr($)[] . zipWith(.) (map(:)l) . map(:)

Мы также можем сделать это без очков

blend' = (foldr($)[].) . (.map(:)) . zipWith(.) . map(:)


Как это работает: сначала украсьте оба списка с операторами cons
\[1,2,3] [4,5,6] -> [1:, 2:, 3:] [4:, 5:, 6:]

тогда мы архивируем это вместе с составом функции

-> [(1:).(4:), (2:).(5:), (3:).(6:)]

и, наконец, сверните приложение всех этих композиций справа на пустой список

-> (1:).(4:) $ (2:).(5:) $ (3:).(6:) $ [] = 1:4:2:5:3:6:[] = [1,4,2,5,3,6]
...